diff --git a/.gitignore b/.gitignore index a6bf83c3844..acc7d75c224 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ Docs/INFO_BIN Docs/INFO_SRC Makefile TAGS +mariadb-plugin-columnstore.install.generated Testing/ tmp/ VERSION.dep diff --git a/client/my_readline.h b/client/my_readline.h index ec43d81f2c0..2ff5edcf31c 100644 --- a/client/my_readline.h +++ b/client/my_readline.h @@ -34,9 +34,10 @@ typedef struct st_line_buffer bool truncated; } LINE_BUFFER; -extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file); extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str); extern char *batch_readline(LINE_BUFFER *buffer, bool binary_mode); extern void batch_readline_end(LINE_BUFFER *buffer); +extern bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size, + ulong max_size); #endif /* CLIENT_MY_READLINE_INCLUDED */ diff --git a/client/mysql.cc b/client/mysql.cc index dcd7a95b1ca..81a890b77c8 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1216,6 +1216,88 @@ inline int get_command_index(char cmd_char) return -1; } +static LINE_BUFFER *batch_readline_init(ulong max_size, const char *path) +{ + LINE_BUFFER *line_buff; + File file; + MY_STAT input_file_stat; + char buff[FN_REFLEN + 512]; + + if (path) + { + file= my_open(path, O_RDONLY | O_BINARY, MYF(0)); + if (file < 0 && my_errno == ENOENT && script_dir) + { + char full_path[FN_REFLEN]; + strxnmov(full_path, sizeof(full_path)-1, script_dir, "/", path, NULL); + file= my_open(full_path, O_RDONLY | O_BINARY, MYF(0)); + } + if (file < 0) + { +#ifdef _WIN32 + if (my_errno == EACCES && my_stat(path, &input_file_stat, MYF(0)) && + MY_S_ISDIR(input_file_stat.st_mode)) + my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'", + FN_REFLEN, path); + else +#endif + my_snprintf(buff, sizeof(buff), "Failed to open file '%.*s', error: %d", + FN_REFLEN, path, my_errno); + put_info(buff, INFO_ERROR, 0); + return 0; + } + } + else + { + file= my_fileno(stdin); + } + + if (my_fstat(file, &input_file_stat, MYF(0))) + { + my_snprintf(buff, sizeof(buff), "Failed to stat file '%.*s', error: %d", + FN_REFLEN, path ? path : "stdin", my_errno); + goto err1; + } + + if (MY_S_ISDIR(input_file_stat.st_mode)) + { + my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'", + FN_REFLEN, path ? path : "stdin"); + goto err1; + } + +#ifndef _WIN32 + if (MY_S_ISBLK(input_file_stat.st_mode)) + { + my_snprintf(buff, sizeof(buff), "Can't read from a block device '%.*s'", + FN_REFLEN, path ? path : "stdin"); + goto err1; + } +#endif + + if (!(line_buff= (LINE_BUFFER*) my_malloc(PSI_NOT_INSTRUMENTED, + sizeof(*line_buff), + MYF(MY_WME | MY_ZEROFILL)))) + { + goto err; + } + + if (init_line_buffer(line_buff, file, IO_SIZE, max_size)) + { + my_free(line_buff); + goto err; + } + + return line_buff; + +err1: + put_info(buff, INFO_ERROR, 0); +err: + if (path) + my_close(file, MYF(0)); + return 0; +} + static int delimiter_index= -1; static int charset_index= -1; static int sandbox_index= -1; @@ -1290,10 +1372,8 @@ int main(int argc,char *argv[]) } if (status.batch && !status.line_buff && - !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin))) + !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, NULL))) { - put_info("Can't initialize batch_readline - may be the input source is " - "a directory or a block device.", INFO_ERROR, 0); free_defaults(defaults_argv); my_end(0); exit(1); @@ -4742,11 +4822,9 @@ static int com_connect(String *buffer, char *line) static int com_source(String *, char *line) { char source_name[FN_REFLEN], *end, *param; - char full_path[FN_REFLEN]; LINE_BUFFER *line_buff; int error; STATUS old_status; - FILE *sql_file; my_bool save_ignore_errors; if (status.sandbox) @@ -4766,27 +4844,10 @@ static int com_source(String *, char *line) end--; end[0]=0; unpack_filename(source_name,source_name); - /* open file name */ - if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0)))) - { - if (script_dir) - { - snprintf(full_path, sizeof(full_path), "%s/%s", script_dir, source_name); - sql_file = my_fopen(full_path, O_RDONLY | O_BINARY, MYF(0)); - } - } - if (!sql_file) + if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, source_name))) { - char buff[FN_REFLEN + 60]; - sprintf(buff, "Failed to open file '%s', error: %d", source_name, errno); - return put_info(buff, INFO_ERROR, 0); - } - - if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file))) - { - my_fclose(sql_file,MYF(0)); - return put_info("Can't initialize batch_readline", INFO_ERROR, 0); + return ignore_errors ? -1 : 1; } /* Save old status */ @@ -4805,7 +4866,7 @@ static int com_source(String *, char *line) ignore_errors= save_ignore_errors; status=old_status; // Continue as before in_com_source= aborted= 0; - my_fclose(sql_file,MYF(0)); + my_close(line_buff->file, MYF(0)); batch_readline_end(line_buff); /* If we got an error during source operation, don't abort the client diff --git a/client/mysqldump.cc b/client/mysqldump.cc index 618ac25e809..811bf73ab90 100644 --- a/client/mysqldump.cc +++ b/client/mysqldump.cc @@ -7311,6 +7311,85 @@ static void init_connection_pool(uint n_connections) connection_pool.init(conn, n_connections); } +/* + Fix permissions and ownership of given directory to be the same + as the root output directory. + + The function is used for newly created database directories, + together with --dir option + + This function is not thread-safe, nor does it need to be, because + it is called from the main thread only. + + chmod/chown errors are ignored after the first one, with a warning printed, + so it is really the best effort attempt. We might see an error later + if the server can't write into the directory, and this will be the + real error. + + On Windows, this function does nothing, because the permissions are + inherited from the parent directory anyway. + + @param dirpath Directory path +*/ +static void fix_permissions_and_owner(const char *dirpath) +{ +#ifndef _WIN32 + // Permissions and ownership of output directory (--dir) + static struct stat st_out_dir; + + static bool fix_perms= true; // Try fixing permission bits + static bool fix_ownership_uid= true; // Try fixing user+group ownership + static bool fix_ownership_gid= false; // Try fixing group ownership only + + static bool first_time= true; + if (first_time) + { + /* Find out permissions and ownership of output directory */ + first_time= false; + if (stat(opt_dir, &st_out_dir) != 0) + { + die(EX_CONSCHECK, "Error: cannot stat output directory %s, errno %d", + opt_dir, errno); + } + } + + /* Change permissions to be the same as for the output directory*/ + if (fix_perms && + chmod(dirpath, st_out_dir.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) + { + fprintf(stderr, + "Warning: cannot set permissions on directory %s, errno %d\n", + dirpath, errno); + fix_perms= false; + } + + /* + Change ownership to be the same as backup root dir. + If user can't be changed, try changing owner group only. + */ + if (fix_ownership_uid && + chown(dirpath, st_out_dir.st_uid, st_out_dir.st_gid)) + { + // No warning, error is expected, unless current user is root. + fix_ownership_uid= false; + fix_ownership_gid= true; + } + + if (fix_ownership_gid && chown(dirpath, -1, st_out_dir.st_gid)) + { + if (!(st_out_dir.st_mode & S_IWOTH)) + { + /* Only warn if directory is not world-writable (group ownership + matters more in this case), to avoid spamming stderr.*/ + fprintf(stderr, + "Warning: cannot set group ownership on directory %s, errno %d\n", + dirpath, errno); + } + fix_ownership_gid= false; + } +#endif +} + /* If --dir option is in use, ensure that output directory for given db exists. @@ -7330,6 +7409,7 @@ static void ensure_out_dir_exists(const char *db) } if (my_mkdir(outdir, 0777, MYF(MY_WME))) die(EX_MYSQLERR, "Error creating directory %s", outdir); + fix_permissions_and_owner(outdir); } diff --git a/client/readline.cc b/client/readline.cc index e4014658c08..f88a942f012 100644 --- a/client/readline.cc +++ b/client/readline.cc @@ -23,38 +23,11 @@ #include #include "my_readline.h" -static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size, - ulong max_size); static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str); static size_t fill_buffer(LINE_BUFFER *buffer); static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length); -LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) -{ - LINE_BUFFER *line_buff; - -#ifndef _WIN32 - MY_STAT input_file_stat; - if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) || - MY_S_ISDIR(input_file_stat.st_mode) || - MY_S_ISBLK(input_file_stat.st_mode)) - return 0; -#endif - - if (!(line_buff=(LINE_BUFFER*) - my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*line_buff), - MYF(MY_WME | MY_ZEROFILL)))) - return 0; - if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size)) - { - my_free(line_buff); - return 0; - } - return line_buff; -} - - char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode) { char *pos; @@ -105,8 +78,7 @@ LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str) Functions to handle buffered readings of lines from a stream ******************************************************************************/ -static bool -init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer) +bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer) { buffer->file=file; buffer->bufread=size; diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 6b7b4d698b1..8c120642fe5 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -120,8 +120,8 @@ ELSEIF(DEB) SET(WITH_ZLIB system CACHE STRING "") SET(WITH_LIBWRAP ON) SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON) - # No hurd implementation - IF(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "i686-AT386") + # On Hurd systems (GNU) there is no auth socket implementation + IF(NOT CMAKE_SYSTEM_NAME STREQUAL "GNU") SET(PLUGIN_AUTH_SOCKET YES CACHE STRING "") ENDIF() SET(WITH_EMBEDDED_SERVER ON CACHE BOOL "") diff --git a/cmake/mariadb_connector_c.cmake b/cmake/mariadb_connector_c.cmake index 86e7d5612e2..859f96a8dcc 100644 --- a/cmake/mariadb_connector_c.cmake +++ b/cmake/mariadb_connector_c.cmake @@ -7,12 +7,7 @@ ENDIF() SET(CONC_WITH_SIGNCODE ${SIGNCODE}) SET(SIGN_OPTIONS ${SIGNTOOL_PARAMETERS}) SET(CONC_WITH_EXTERNAL_ZLIB ON) -SET(CLIENT_PLUGIN_PARSEC OFF) -CHECK_INCLUDE_FILES (threads.h HAVE_THREADS_H) -IF(HAVE_THREADS_H) -SET(CLIENT_PLUGIN_PARSEC DYNAMIC) -ENDIF() IF(NOT CONC_WITH_SSL) IF(SSL_DEFINES MATCHES "WOLFSSL") diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 844c240ac5c..80354e52f71 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1237,7 +1237,7 @@ static void backup_file_op_fail(uint32_t space_id, int type, msg("DDL tracking : create %" PRIu32 " \"%.*s\"", space_id, int(len), name); fail = !check_if_skip_table(spacename.c_str()); - if (!opt_no_lock && fail && + if (fail && !opt_no_lock && check_if_fts_table(spacename.c_str())) { /* Ignore the FTS internal table because InnoDB does create intermediate table and their associative FTS @@ -1264,6 +1264,11 @@ static void backup_file_op_fail(uint32_t space_id, int type, break; case FILE_DELETE: fail = !check_if_skip_table(spacename.c_str()) + /* Ignore the FTS internal table because InnoDB may + drop intermediate table and their associative FTS + internal table as a part of inplace rollback operation. + backup_set_alter_copy_lock() downgrades the + MDL_BACKUP_DDL before inplace phase of alter */ && !check_if_fts_table(spacename.c_str()); msg("DDL tracking : delete %" PRIu32 " \"%.*s\"", space_id, int(len), name); @@ -5877,6 +5882,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta) node, 0, dest_name.c_str(), wf_write_through, *this); } + + DBUG_MARIABACKUP_EVENT("after_backup_fix_ddl", {}); } @@ -6120,16 +6127,12 @@ exit: ut_ad(fil_space_t::physical_size(flags) == info.page_size); mysql_mutex_lock(&fil_system.mutex); - fil_space_t* space = fil_space_t::create(uint32_t(info.space_id), - flags, false, 0, - FIL_ENCRYPTION_DEFAULT, true); + std::ignore = fil_space_t::create(uint32_t(info.space_id), + flags, false, 0, + FIL_ENCRYPTION_DEFAULT, true); mysql_mutex_unlock(&fil_system.mutex); - if (space) { - *success = xb_space_create_file(real_name, info.space_id, - flags, &file); - } else { - msg("Can't create tablespace %s\n", dest_space_name); - } + *success = xb_space_create_file(real_name, info.space_id, + flags, &file); goto exit; } diff --git a/include/ilist.h b/include/ilist.h index 3349959e17e..46f706eaef9 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -189,6 +189,9 @@ public: ListNode *prev= pos.node_->prev; ListNode *next= pos.node_->next; + DBUG_ASSERT(prev->next == pos.node_); + DBUG_ASSERT(next->prev == pos.node_); + prev->next= next; next->prev= prev; @@ -202,7 +205,7 @@ public: } void push_back(reference value) noexcept { insert(end(), value); } - void pop_back() noexcept { erase(end()); } + void pop_back() noexcept { erase(--end()); } void push_front(reference value) noexcept { insert(begin(), value); } void pop_front() noexcept { erase(begin()); } diff --git a/include/m_ctype.h b/include/m_ctype.h index 660c5f1c0a2..90b6106f521 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -186,6 +186,15 @@ typedef struct my_uca_level_booster_t This array is used for prefix optimization. */ MY_UCA_WEIGHT2 weight_strings_2bytes_to_1_or_2_weights[0x10000]; + + /* + A helper array to process one-character ASCII strings. + Suitable only for stand-alone characters, + which are known not to be contraction parts, + e.g. the very last character of a string. + */ + uint16 weight_1byte_to_1weight_standalone[0x100]; + } MY_UCA_LEVEL_BOOSTER; diff --git a/include/my_dbug.h b/include/my_dbug.h index 25bcb3b2964..e1b3d204789 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -75,6 +75,7 @@ extern int (*dbug_sanity)(void); #define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0) +#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) #ifdef HAVE_ATTRIBUTE_CLEANUP #define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \ @@ -94,6 +95,7 @@ extern int (*dbug_sanity)(void); #define DBUG_RETURN(a1) return(a1) #define DBUG_VOID_RETURN return #define DBUG_PRINT(keyword,arglist) do{} while(0) +#define DBUG_DUMP(keyword,a1,a2) do{} while(0) #endif #define DBUG_EXECUTE(keyword,a1) \ @@ -111,7 +113,6 @@ extern int (*dbug_sanity)(void); #define DBUG_SET_INITIAL(a1) _db_set_init_ (a1) #define DBUG_PROCESS(a1) _db_process_(a1) #define DBUG_FILE _db_fp_() -#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) #define DBUG_END() _db_end_ () #define DBUG_LOCK_FILE _db_lock_file_() #define DBUG_UNLOCK_FILE _db_unlock_file_() @@ -230,7 +231,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); one should #include . We intentionally avoid including it here to save compilation time. */ -# ifdef DBUG_OFF +# if defined DBUG_OFF || !defined DBUG_TRACE # define DBUG_LOG(keyword, v) do {} while (0) # else # define DBUG_LOG(keyword, v) do { \ diff --git a/include/mysql_com.h b/include/mysql_com.h index b9fae54e7f4..21be527f9dd 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -406,6 +406,13 @@ enum mariadb_field_attr_t #define SERVER_STATUS_ANSI_QUOTES 32768U +/* + Set for stored procedures if the select query returned a row + To check for an empty query, one must also check thd::get_sent_row_count() +*/ + +#define SERVER_STATUS_RETURNED_ROW (1U << 16) + /** Server status flags that must be cleared when starting execution of a new SQL statement. @@ -422,7 +429,8 @@ enum mariadb_field_attr_t SERVER_STATUS_DB_DROPPED |\ SERVER_STATUS_CURSOR_EXISTS|\ SERVER_STATUS_LAST_ROW_SENT|\ - SERVER_SESSION_STATE_CHANGED) + SERVER_SESSION_STATE_CHANGED|\ + SERVER_STATUS_RETURNED_ROW) #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ diff --git a/libmariadb b/libmariadb index 46880b00365..ad30f836240 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 46880b003653a000e9588bd73c8b1dd65088c686 +Subproject commit ad30f8362402012cdeb3adaeb3a14bb55bdbbb76 diff --git a/mariadb-plugin-columnstore.install.generated b/mariadb-plugin-columnstore.install.generated new file mode 100644 index 00000000000..d987525f2a6 --- /dev/null +++ b/mariadb-plugin-columnstore.install.generated @@ -0,0 +1 @@ +#File is generated by ColumnstoreLibrary.cmake, do not edit diff --git a/mysql-test/include/check_connect.inc b/mysql-test/include/check_connect.inc new file mode 100644 index 00000000000..e34d3a4a0d1 --- /dev/null +++ b/mysql-test/include/check_connect.inc @@ -0,0 +1,6 @@ +# Check if connect engine is loaded and enabled + +if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'CONNECT' AND support IN ('YES', 'DEFAULT', 'ENABLED')`) +{ + --skip Test requires connect engine +} diff --git a/mysql-test/include/galera_variables_ok.inc b/mysql-test/include/galera_variables_ok.inc index 9bd31bb32b2..d10bf1fd36e 100644 --- a/mysql-test/include/galera_variables_ok.inc +++ b/mysql-test/include/galera_variables_ok.inc @@ -5,7 +5,7 @@ if (!$_galera_variables_delta) { --let $galera_variables_delta=0 } ---let $galera_variables_expected=`SELECT 51 + $galera_variables_delta` +--let $galera_variables_expected=`SELECT 50 + $galera_variables_delta` --let $galera_variables_count=`SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep%'` diff --git a/mysql-test/lib/generate-ssl-certs.sh b/mysql-test/lib/generate-ssl-certs.sh index f698464b932..1c6cda56fe2 100755 --- a/mysql-test/lib/generate-ssl-certs.sh +++ b/mysql-test/lib/generate-ssl-certs.sh @@ -67,3 +67,156 @@ rm -fv crldir/* cp -v client-cert.crl crldir/`openssl x509 -in client-cert.pem -noout -issuer_hash`.r0 rm -rf demoCA + +# --- Certificate Chain --- +# These tests are inspired from the following commit from MySQL Server +# https://github.com/mysql/mysql-server/commit/969afef933f1872c5f38ea93047ef05c4509c335 +# +# Credits to salman.s.khan@oracle.com +# +# ------------------------------------------------------------------------------------- +# +# STEPS TO GENERATE THE FOLLOWING CHAINED CERTIFICATES WHICH IS USED IN THE TEST CASE : +# +# +---------+ +# | Root CA | +# +---------+ +# | +# /------------+-----------\ +# | | +# +------------------+ +------------------+ +# | Intermediate CA1 | | Intermediate CA2 | +# +------------------+ +------------------+ +# | | +# +-------------+ +-------------+ +# | Server | | Client | +# | certificate | | certificate | +# +-------------+ +-------------+ + +cd cachain + +mkdir ca +mkdir server +mkdir clients + +mkdir ca/root.certs +touch ca/root.index.txt +touch ca/root.index.txt.attr +echo '01' > ca/root.serial + +cat > ca/root.cfg << EOF +[ ca ] +default_ca = CA_default +[ CA_default ] +dir = $PWD/ca +certs = \$dir/certs +database = \$dir/root.index.txt +serial = \$dir/root.serial +policy= policy_match +[ policy_match ] +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional +[ v3_ca ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer +basicConstraints = critical,CA:TRUE +keyUsage = critical,keyCertSign,cRLSign +[ v3_ca_intermediate ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer +basicConstraints = critical,CA:TRUE,pathlen:0 +keyUsage = critical,keyCertSign,cRLSign +EOF + +# Generate Root CA key and cert +openssl genrsa -out ca/root.key 4096 +openssl req -new -x509 '-sha256' -key ca/root.key -out ca/root.crt -days 7200 -subj "/O=MariaDB/OU=MariaDB/CN=Root CA" -config ca/root.cfg -extensions v3_ca + +# Generate Intermediate CA1 key and cert +openssl genrsa -out ca/intermediate_ca1.key 4096 +openssl req -new '-sha256' -key ca/intermediate_ca1.key -out ca/intermediate_ca1.csr -subj "/O=MariaDB/OU=MariaDB/CN=Intermediate CA1" + +openssl ca -batch -days 7200 -notext -md sha256 -in ca/intermediate_ca1.csr -out ca/intermediate_ca1.crt -keyfile ca/root.key -cert ca/root.crt -outdir ca/root.certs/ -config ca/root.cfg -extensions v3_ca_intermediate + +mkdir ca/intermediate_ca1.certs +touch ca/intermediate_ca1.index.txt +touch ca/intermediate_ca1.index.txt.attr +echo '01' > ca/intermediate_ca1.serial + +cat > ca/intermediate_ca1.cfg << EOF +[ ca ] +default_ca = CA_default +[ CA_default ] +dir = $PWD/ca +certs = \$dir/intermediate_ca1.certs +database = \$dir/intermediate_ca1.index.txt +serial = \$dir/intermediate_ca1.serial +policy= policy_match +[ policy_match ] +commonName = supplied +[ alt_names ] +DNS.1 = localhost +IP.1 = 127.0.0.1 +[ server_cert ] +basicConstraints = CA:FALSE +keyUsage = critical,digitalSignature,keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names +EOF + +# Generate Server key and cert +openssl genrsa -out server/server.key 4096 +openssl req -new '-sha256' -key server/server.key -out server/server.csr -subj "/CN=localhost" + +openssl ca -batch -days 7200 -notext -md sha256 -in server/server.csr -out server/server.crt -keyfile ca/intermediate_ca1.key -cert ca/intermediate_ca1.crt -outdir ca/intermediate_ca1.certs/ -config ca/intermediate_ca1.cfg -extensions server_cert + +# Generate Intermediate CA2 key and cert +openssl genrsa -out ca/intermediate_ca2.key 4096 + +openssl req -new '-sha256' -key ca/intermediate_ca2.key -out ca/intermediate_ca2.csr -subj "/O=MariaDB/OU=MariaDB/CN=Intermediate CA2" +openssl ca -batch -days 7200 -notext -md sha256 -in ca/intermediate_ca2.csr -out ca/intermediate_ca2.crt -keyfile ca/root.key -cert ca/root.crt -outdir ca/root.certs/ -config ca/root.cfg -extensions v3_ca_intermediate + +mkdir ca/intermediate_ca2.certs +touch ca/intermediate_ca2.index.txt +touch ca/intermediate_ca2.index.txt.attr +echo '01' > ca/intermediate_ca2.serial + +cat > ca/intermediate_ca2.cfg << EOF +[ ca ] +default_ca = CA_default +[ CA_default ] +dir = $PWD/ca +certs = \$dir/intermediate_ca2.certs +database = \$dir/intermediate_ca2.index.txt +serial = \$dir/intermediate_ca2.serial +policy= policy_match +[ policy_match ] +commonName = supplied +[ client_cert ] +basicConstraints = CA:FALSE +keyUsage = critical,digitalSignature,keyEncipherment +extendedKeyUsage = clientAuth +EOF + +# Generate Client key and cert +openssl genrsa -out clients/client.key 4096 +openssl req -new '-sha256' -key clients/client.key -out clients/client.csr -subj "/CN=client" + +openssl ca -batch -days 7200 -notext -md sha256 -in clients/client.csr -out clients/client.crt -keyfile ca/intermediate_ca2.key -cert ca/intermediate_ca2.crt -outdir ca/intermediate_ca2.certs/ -config ca/intermediate_ca2.cfg -extensions client_cert + +cat server/server.crt ca/intermediate_ca1.crt > server/server.cachain + +cat clients/client.crt ca/intermediate_ca2.crt > clients/client.cachain + +cat ca/root.crt ca/intermediate_ca1.crt > ca/root_intermediate_ca1.crt + +# Generate Unrelated Root CA key and cert +openssl genrsa -out ca/unrelated_root.key 4096 +openssl req -new -x509 '-sha256' -key ca/unrelated_root.key -out ca/unrelated_root.crt -days 7200 -subj "/O=MariaDB/OU=MariaDB/CN=Root CA" -config ca/root.cfg -extensions v3_ca + +cp -v ca/root.crt ca/root_intermediate_ca1.crt ca/unrelated_root.crt server/server.key server/server.cachain clients/client.key clients/client.cachain ./ +rm -rf ca server clients + +cd .. diff --git a/mysql-test/main/chained_ssl_certificates.opt b/mysql-test/main/chained_ssl_certificates.opt new file mode 100644 index 00000000000..bb2f8e1d883 --- /dev/null +++ b/mysql-test/main/chained_ssl_certificates.opt @@ -0,0 +1,3 @@ +--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt +--ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key +--ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain diff --git a/mysql-test/main/chained_ssl_certificates.result b/mysql-test/main/chained_ssl_certificates.result new file mode 100644 index 00000000000..08911b0c936 --- /dev/null +++ b/mysql-test/main/chained_ssl_certificates.result @@ -0,0 +1,12 @@ +call mtr.add_suppression("Server SSL certificate doesn't verify"); +CREATE USER 'user1'@'%' REQUIRE SSL; +Variable_name Value +Ssl_version TLS + +Restart server and provide ssl-ca comprising intermediate_ca1 in addition to the root ca. +Variable_name Value +Ssl_version TLS + +Restart server and provide unrelated ssl-ca at server startup +ERROR 2026 (HY000): TLS/SSL error: +DROP USER 'user1'; diff --git a/mysql-test/main/chained_ssl_certificates.test b/mysql-test/main/chained_ssl_certificates.test new file mode 100644 index 00000000000..9d315e94807 --- /dev/null +++ b/mysql-test/main/chained_ssl_certificates.test @@ -0,0 +1,74 @@ +# These tests are inspired from the following commit from MySQL Server +# https://github.com/mysql/mysql-server/commit/969afef933f1872c5f38ea93047ef05c4509c335 + +# Credits to salman.s.khan@oracle.com + +##################################################################################### +# This test verifies MariaDB can handle chained ssl certificate +# This test uses chained ssl certificates which is depicted as +# below:- +# +# +---------+ +# | Root CA | +# +---------+ +# | +# /------------+-----------\ +# | | +# +------------------+ +------------------+ +# | Intermediate CA1 | | Intermediate CA2 | +# +------------------+ +------------------+ +# | | +# +-------------+ +-------------+ +# | Server | | Client | +# | certificate | | certificate | +# +-------------+ +-------------+ +# +# certificates that may be helpful for chain construction. +# In order to validate server cert correctly, we need to +# provide the trusted root certificate and the untrusted +# intermediate certificates as part of ssl-ca. Hence +# root_intermediate_ca1.crt (trusted root certificate + +# untrusted intermediate ca1 certificate) is passed as with +# --ssl-ca option + +--source include/not_embedded.inc +--source include/have_ssl_communication.inc + +#Suppress warning by the server certificate verification check: unrelated CA +call mtr.add_suppression("Server SSL certificate doesn't verify"); + +CREATE USER 'user1'@'%' REQUIRE SSL; + +--replace_result TLSv1.3 TLS TLSv1.2 TLS +--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'" + +--echo +--echo Restart server and provide ssl-ca comprising intermediate_ca1 in addition to the root ca. +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--write_line "restart:--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root_intermediate_ca1.crt --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_result TLSv1.3 TLS TLSv1.2 TLS +--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'" + +--echo +--echo Restart server and provide unrelated ssl-ca at server startup +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--write_line "restart:--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/unrelated_root.crt --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_regex /(ERROR 2026 \(HY000\): TLS\/SSL error:).*/\1/ +--error 1 +--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/unrelated_root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'" 2>&1 +--echo + +# Cleanup +DROP USER 'user1'; diff --git a/mysql-test/main/create_w_max_indexes_128.result b/mysql-test/main/create_w_max_indexes_128.result index 112df1b7c41..e54c27b8270 100644 --- a/mysql-test/main/create_w_max_indexes_128.result +++ b/mysql-test/main/create_w_max_indexes_128.result @@ -470,7 +470,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci flush tables; show create table t1; Table Create Table @@ -619,7 +619,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1; create table t1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int, c11 int, c12 int, c13 int, c14 int, c15 int, c16 int); @@ -1092,7 +1092,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci flush tables; show create table t1; Table Create Table @@ -1241,7 +1241,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci alter table t1 add key a129_long_123456789_123456789_123456789_123456789_123456789_1234 ( c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16); diff --git a/mysql-test/main/cte_recursive.result b/mysql-test/main/cte_recursive.result index 03e265cb4ea..c2940fe38fc 100644 --- a/mysql-test/main/cte_recursive.result +++ b/mysql-test/main/cte_recursive.result @@ -6058,4 +6058,111 @@ drop table t1; # SELECT ( WITH RECURSIVE x AS ( WITH x AS ( SELECT 1 FROM t14 ) SELECT x ) , t14 AS ( SELECT 1 UNION SELECT 'x' FROM x ) SELECT x FROM x WHERE ( SELECT x FROM x ) ) ; ERROR 42S22: Unknown column 'x' in 'SELECT' +# +# MDEV-32299 Segfault when preparing unreferenced select in recursive CTE +# +SELECT ( WITH RECURSIVE x AS ( SELECT * FROM ( SELECT UTC_TIMESTAMP FROM ( SELECT ( WITH x AS ( WITH x AS ( SELECT * FROM x ) SELECT 1 ) SELECT 1 ) ) x ) x UNION SELECT NULL ) ( SELECT x FROM x ) ) ; +ERROR 42S22: Unknown column 'x' in 'SELECT' +select ( +with recursive x as ( +select * from ( +select utc_timestamp +from ( +select ( +with x as ( +with x as ( +select * from x +) +select 1 +) +select 1 +) s +) y +) z +union +select null +) +(select x from x) +); +ERROR 42S22: Unknown column 'x' in 'SELECT' +select ( +with recursive r as ( +select * from ( +with a as ( +select * from r +) +select 1 +) y +union +select 1 +) +(select * from r) +); +( +with recursive r as ( +select * from ( +with a as ( +select * from r +) +select 1 +) y +union +select 1 +) +(select * from r) +) +1 +create table t1 (x int); +with recursive r as ( +select f1 from ( +with a as ( +select x from t1 +) +select 1 as f1 +) y +union +select null +) +(select * from r); +f1 +1 +NULL +with recursive r as ( +select f1 from ( +with a as ( +select f2 from t1 +) +select 1 as f1 +) y +union +select null +) +(select * from r); +ERROR 42S22: Unknown column 'f2' in 'SELECT' +drop table t1; +with recursive r as ( +select 1 as f1 +union +select f1 from ( +with a as ( +select f1 from r +) +select 1 as f1 +) y +) +(select f1 from r); +f1 +1 +with recursive r as ( +select 1 as f1 +union +select f1 from ( +with a as ( +select f2 from r +) +select 1 as f1 +) y +) +(select f1 from r); +ERROR 42S22: Unknown column 'f2' in 'SELECT' # End of 10.6 tests diff --git a/mysql-test/main/cte_recursive.test b/mysql-test/main/cte_recursive.test index 88a9cefe80e..30f94667b2d 100644 --- a/mysql-test/main/cte_recursive.test +++ b/mysql-test/main/cte_recursive.test @@ -3,6 +3,8 @@ --source include/no_msan_without_big.inc --source include/not_valgrind.inc --source include/have_innodb.inc +# --view-protocol fails due to MDEV-37119 for MDEV-32299 +--source include/no_view_protocol.inc create table t1 (a int, b varchar(32)); insert into t1 values @@ -4066,4 +4068,121 @@ drop table t1; --error ER_BAD_FIELD_ERROR SELECT ( WITH RECURSIVE x AS ( WITH x AS ( SELECT 1 FROM t14 ) SELECT x ) , t14 AS ( SELECT 1 UNION SELECT 'x' FROM x ) SELECT x FROM x WHERE ( SELECT x FROM x ) ) ; +--echo # +--echo # MDEV-32299 Segfault when preparing unreferenced select in recursive CTE +--echo # + +# As in bug report +--error ER_BAD_FIELD_ERROR +SELECT ( WITH RECURSIVE x AS ( SELECT * FROM ( SELECT UTC_TIMESTAMP FROM ( SELECT ( WITH x AS ( WITH x AS ( SELECT * FROM x ) SELECT 1 ) SELECT 1 ) ) x ) x UNION SELECT NULL ) ( SELECT x FROM x ) ) ; + +#0 0x00005555569dff7b in TABLE_LIST::reset_const_table (this=0x7fffe0019938) at ../src/sql/table.cc:9615 +#1 0x00005555569dffd4 in TABLE_LIST::reset_const_table (this=0x7fffe001a8c0) at ../src/sql/table.cc:9622 +--error ER_BAD_FIELD_ERROR +select ( + with recursive x as ( + select * from ( + select utc_timestamp + from ( + select ( + with x as ( + with x as ( + select * from x + ) + select 1 + ) + select 1 + ) s + ) y + ) z + + union + + select null + ) + (select x from x) +); + +#6 0x00007ffff7639206 in __assert_fail (assertion=0x555555e121b6 "table_ref->table || table_ref->view", file=0x555555cdf138 "../src/sql/table.cc", line=7305, function=0x555555e30e24 "void Field_iterator_table_ref::set_field_iterator()") at ./assert/assert.c:101 +#7 0x00005555569da013 in Field_iterator_table_ref::set_field_iterator (this=0x7ffff0a9afc0) at ../src/sql/table.cc:7305 +select ( + with recursive r as ( + select * from ( + with a as ( + select * from r + ) + select 1 + ) y + + union + + select 1 + ) + (select * from r) +); + +# Field resolution in unreferenced: +create table t1 (x int); + +with recursive r as ( + select f1 from ( + with a as ( + select x from t1 + ) + select 1 as f1 + ) y + + union + + select null +) +(select * from r); + +--error ER_BAD_FIELD_ERROR +with recursive r as ( + select f1 from ( + with a as ( + select f2 from t1 + ) + select 1 as f1 + ) y + + union + + select null +) +(select * from r); + +drop table t1; + +with recursive r as ( + select 1 as f1 + + union + + select f1 from ( + with a as ( + select f1 from r + ) + select 1 as f1 + ) y +) +(select f1 from r); + +--error ER_BAD_FIELD_ERROR +with recursive r as ( + select 1 as f1 + + union + + select f1 from ( + with a as ( + select f2 from r + ) + select 1 as f1 + ) y +) +(select f1 from r); + + --echo # End of 10.6 tests diff --git a/mysql-test/main/features.result b/mysql-test/main/features.result index 0fec83f363e..2f0c4193698 100644 --- a/mysql-test/main/features.result +++ b/mysql-test/main/features.result @@ -225,3 +225,4 @@ show status like "Feature_vector_index"; Variable_name Value Feature_vector_index 2 drop table t1; +# End of 11.8 tests diff --git a/mysql-test/main/features.test b/mysql-test/main/features.test index 3d2a03df545..15cc5630c55 100644 --- a/mysql-test/main/features.test +++ b/mysql-test/main/features.test @@ -171,6 +171,7 @@ show status like "feature_into_%"; --echo # Feature vector index --echo # +--disable_service_connection create table t1 (id int auto_increment primary key, u vector(5) not null, vector index (u)); select * from t1; @@ -178,3 +179,6 @@ select * from t1; select * from t1; show status like "Feature_vector_index"; drop table t1; +--enable_service_connection + +--echo # End of 11.8 tests diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 8631a30e800..5a80c2cc8c4 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -5371,9 +5371,10 @@ SET CHARACTER SET default; SELECT json_array_intersect(@a,@b); json_array_intersect(@a,@b) NULL +# # MDEV-36809: json_array_intersect crashs when unused table ref provided # -select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from mysql.user; +select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x; result [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] @@ -5386,11 +5387,16 @@ result # # MDEV-37864: mysql-test/mtr --cursor main.func_json fails # -select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from mysql.user; +select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x; result [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] [["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]] +# +# MDEV-33640: Server crashes at my_hash_free +# +SELECT JSON_SCHEMA_VALID('{"properties": "a_string": {"pattern": "^[5-9]$"}}}', '{"a_string": "8"}'); +ERROR HY000: Invalid value for keyword properties # End of 11.4 Test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 99446292334..ae89b2c7469 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -4265,15 +4265,24 @@ SET CHARACTER SET default; SELECT json_array_intersect(@a,@b); +--echo # --echo # MDEV-36809: json_array_intersect crashs when unused table ref provided --echo # -select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from mysql.user; +select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x; SELECT ( WITH x AS ( WITH x ( x ) AS ( SELECT ( 1.000000 ) ) SELECT x FROM x ) SELECT * FROM x WHERE ( SELECT AVG ( x ) OVER ( ORDER BY JSON_ARRAY_INTERSECT ( '[["1", "7"], ["2", "6"], ["3", "8"]]' , '[["2","6"],["3","8"],["4","5"],["1","7"]]' ) ) FROM x ) ) as result; --echo # --echo # MDEV-37864: mysql-test/mtr --cursor main.func_json fails --echo # -select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from mysql.user; +select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x; + + +--echo # +--echo # MDEV-33640: Server crashes at my_hash_free +--echo # + +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID('{"properties": "a_string": {"pattern": "^[5-9]$"}}}', '{"a_string": "8"}'); --echo # End of 11.4 Test diff --git a/mysql-test/main/func_regexp_pcre.result b/mysql-test/main/func_regexp_pcre.result index cbf921293f4..bfb80943fb0 100644 --- a/mysql-test/main/func_regexp_pcre.result +++ b/mysql-test/main/func_regexp_pcre.result @@ -791,7 +791,7 @@ SELECT 'AB' RLIKE 'A# this is a comment\nB'; 1 SET default_regex_flags=DEFAULT; SELECT 'Aq' RLIKE 'A\\q'; -ERROR 42000: Regex error 'unrecognized character follows \ at offset 2' +ERROR 42000: Regex error 'unrecognized character follows \ at offset 3' SET default_regex_flags='EXTRA'; SELECT 'A' RLIKE 'B'; 'A' RLIKE 'B' diff --git a/mysql-test/main/func_regexp_pcre.test b/mysql-test/main/func_regexp_pcre.test index 1c89112ee8f..ac934db5d87 100644 --- a/mysql-test/main/func_regexp_pcre.test +++ b/mysql-test/main/func_regexp_pcre.test @@ -382,6 +382,8 @@ SELECT 'AB' RLIKE 'A B'; SELECT 'AB' RLIKE 'A# this is a comment\nB'; SET default_regex_flags=DEFAULT; +# pcre2 versions differ in the reported error offset for invalid escapes +--replace_regex /offset 2/offset 3/ --error ER_REGEXP_ERROR SELECT 'Aq' RLIKE 'A\\q'; diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index 94528439b49..fd604a363a6 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -371,7 +371,7 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363 # Expected results are 115.2970604672862 and 36.23335610879993, but IA64 returns # slightly different values due to fused multiply-add instructions. ---replace_result 115.29706047613604 115.2970604672862 36.23335611157958 36.23335610879993 +--replace_regex /115.2970604[67]\d+/115.2970604672862/ /36.233356111579\d+/36.23335610879993/ select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from t1 where object_id=85998; diff --git a/mysql-test/main/grant_kill.result b/mysql-test/main/grant_kill.result index 2f82e347dd5..fbae4de436b 100644 --- a/mysql-test/main/grant_kill.result +++ b/mysql-test/main/grant_kill.result @@ -14,11 +14,9 @@ GRANT ALL PRIVILEGES ON *.* TO bar@localhost; REVOKE CONNECTION ADMIN ON *.* FROM bar@localhost; connect foo,localhost,foo,,; connect bar,localhost,bar,,; -SELECT user FROM information_schema.processlist ORDER BY user; +SELECT user FROM information_schema.processlist WHERE id=$id; user -bar foo -root KILL ID; ERROR HY000: You are not owner of thread ID disconnect foo; @@ -35,11 +33,9 @@ CREATE USER bar@localhost; GRANT PROCESS, CONNECTION ADMIN ON *.* TO bar@localhost; connect foo,localhost,foo,,; connect bar,localhost,bar,,; -SELECT user FROM information_schema.processlist ORDER BY user; +SELECT user FROM information_schema.processlist WHERE id=$id; user -bar foo -root KILL ID; connection default; disconnect foo; diff --git a/mysql-test/main/grant_kill.test b/mysql-test/main/grant_kill.test index 912e4301a10..1e249536c75 100644 --- a/mysql-test/main/grant_kill.test +++ b/mysql-test/main/grant_kill.test @@ -19,9 +19,9 @@ CREATE USER bar@localhost; GRANT ALL PRIVILEGES ON *.* TO bar@localhost; REVOKE CONNECTION ADMIN ON *.* FROM bar@localhost; --connect (foo,localhost,foo,,) -let $id=`(SELECT id FROM INFORMATION_SCHEMA.PROCESSLIST WHERE user='foo')`; +let $id=`select connection_id()`; --connect (bar,localhost,bar,,) -SELECT user FROM information_schema.processlist ORDER BY user; +evalp SELECT user FROM information_schema.processlist WHERE id=$id; --replace_result $id ID --error ER_KILL_DENIED_ERROR --eval KILL $id @@ -40,9 +40,9 @@ GRANT SELECT ON *.* TO foo@localhost; CREATE USER bar@localhost; GRANT PROCESS, CONNECTION ADMIN ON *.* TO bar@localhost; --connect (foo,localhost,foo,,) -let $id=`(SELECT id FROM INFORMATION_SCHEMA.PROCESSLIST WHERE user='foo')`; +let $id=`select connection_id()`; --connect (bar,localhost,bar,,) -SELECT user FROM information_schema.processlist ORDER BY user; +evalp SELECT user FROM information_schema.processlist WHERE id=$id; --replace_result $id ID --eval KILL $id --connection default diff --git a/mysql-test/main/group_min_max_innodb.result b/mysql-test/main/group_min_max_innodb.result index 4a6d98a8f3b..87b718f53ed 100644 --- a/mysql-test/main/group_min_max_innodb.result +++ b/mysql-test/main/group_min_max_innodb.result @@ -180,7 +180,7 @@ F 17 EXPLAIN SELECT c1, max(i2) FROM t1 WHERE (c1 = 'C' OR c1 = 'F' ) AND ( i2 = 17 ) GROUP BY c1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range k1 k1 5 NULL 2 Using where +1 SIMPLE t1 range k1 k1 5 NULL 2 Using where; Using index for group-by SELECT c1, max(i2) FROM t1 WHERE (c1 = 'C' OR c1 = 'F' ) AND ( i2 = 17 ) GROUP BY c1; c1 max(i2) @@ -438,6 +438,43 @@ disconnect con1; connection default; DROP TABLE t1; SET GLOBAL innodb_lru_scan_depth= @lru_depth.save; +# +# MDEV-38426: Clustered PK not used for Loose Index Scan optimization +# +create table t1 ( +col1 int not null, +col2 int not null, +col3 int, +primary key(col1, col2) +) engine=innodb; +insert into t1 select +A.seq, +B.seq, +A.seq +from +seq_1_to_10 A, +seq_1_to_1000 B; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# This must use Loose Scan: +explain select distinct col1 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 4 NULL 11 Using index for group-by +# This must use Loose Scan: +explain select col1 from t1 group by col1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 4 NULL 11 Using index for group-by +# This must use Loose Scan: +explain select col1, min(col2) from t1 group by col1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 4 NULL 11 Using index for group-by +# This will not use Loose Index Scan as col3 is not in PK: +explain select col1, min(col2), col3 from t1 group by col1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 10000 +drop table t1; set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/group_min_max_innodb.test b/mysql-test/main/group_min_max_innodb.test index 1bddd6ed4bb..165580a7f8f 100644 --- a/mysql-test/main/group_min_max_innodb.test +++ b/mysql-test/main/group_min_max_innodb.test @@ -323,6 +323,40 @@ while ($run) DROP TABLE t1; SET GLOBAL innodb_lru_scan_depth= @lru_depth.save; +--echo # +--echo # MDEV-38426: Clustered PK not used for Loose Index Scan optimization +--echo # +--source include/have_sequence.inc + +create table t1 ( + col1 int not null, + col2 int not null, + col3 int, + primary key(col1, col2) +) engine=innodb; +insert into t1 select + A.seq, + B.seq, + A.seq +from + seq_1_to_10 A, + seq_1_to_1000 B; +analyze table t1; + +--echo # This must use Loose Scan: +explain select distinct col1 from t1; + +--echo # This must use Loose Scan: +explain select col1 from t1 group by col1; + +--echo # This must use Loose Scan: +explain select col1, min(col2) from t1 group by col1; + +--echo # This will not use Loose Index Scan as col3 is not in PK: +explain select col1, min(col2), col3 from t1 group by col1; + +drop table t1; + set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/index_intersect_innodb.result b/mysql-test/main/index_intersect_innodb.result index 9ce05a97b90..3b7a0dfbccd 100644 --- a/mysql-test/main/index_intersect_innodb.result +++ b/mysql-test/main/index_intersect_innodb.result @@ -485,7 +485,7 @@ SELECT * FROM City WHERE ID BETWEEN 3701 AND 4000 AND Population > 1000000 AND Country BETWEEN 'S' AND 'Z'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE City index_merge PRIMARY,Population,Country PRIMARY,Population 4,4 NULL # Using sort_intersect(PRIMARY,Population); Using where +1 SIMPLE City range PRIMARY,Population,Country PRIMARY 4 NULL # Using where EXPLAIN SELECT * FROM City WHERE ID BETWEEN 3001 AND 4000 AND Population > 600000 diff --git a/mysql-test/main/innodb_ext_key,off.rdiff b/mysql-test/main/innodb_ext_key,off.rdiff index 8b24cc9a663..4db9110f049 100644 --- a/mysql-test/main/innodb_ext_key,off.rdiff +++ b/mysql-test/main/innodb_ext_key,off.rdiff @@ -5,7 +5,7 @@ select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 8 const,const 1 Using index -+1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where flush status; select count(*) from lineitem where l_orderkey=130 and l_shipdate='1992-07-01'; count(*) @@ -14,7 +14,7 @@ Handler_read_key 1 Handler_read_last 0 -Handler_read_next 1 -+Handler_read_next 6 ++Handler_read_next 5 Handler_read_prev 0 Handler_read_retry 0 Handler_read_rnd 0 @@ -95,7 +95,7 @@ where l_shipdate='1992-07-01' and l_orderkey=130; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -+1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 const 6 Using where; Using index ++1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 const 5 Using where flush status; select max(l_linenumber) from lineitem where l_shipdate='1992-07-01' and l_orderkey=130; @@ -104,7 +104,7 @@ Handler_read_key 1 Handler_read_last 0 -Handler_read_next 0 -+Handler_read_next 6 ++Handler_read_next 5 Handler_read_prev 0 Handler_read_retry 0 Handler_read_rnd 0 diff --git a/mysql-test/main/insert_notembedded.result b/mysql-test/main/insert_notembedded.result index 5df69cc8ffe..d7beca6d049 100644 --- a/mysql-test/main/insert_notembedded.result +++ b/mysql-test/main/insert_notembedded.result @@ -121,3 +121,48 @@ connection default; DROP DATABASE meow; set local sql_mode=default; set global sql_mode=default; +# +# MDEV-37950: INSERT ... RETURNING exposes columns for which +# the user lacks SELECT privilege +# +CREATE USER regular; +GRANT INSERT ON *.* TO regular; +GRANT DELETE ON *.* TO regular; +CREATE DATABASE test1; +DROP TABLE IF EXISTS test1.t_trigger_test1; +Warnings: +Note 1051 Unknown table 'test1.t_trigger_test1' +CREATE TABLE test1.t_trigger_test1 ( +id INT AUTO_INCREMENT PRIMARY KEY, +name VARCHAR(50), +note VARCHAR(100) +); +CREATE TRIGGER test1.trg_before_insert +BEFORE INSERT ON test1.t_trigger_test1 +FOR EACH ROW +BEGIN +SET NEW.name = CONCAT('BEFORE_', NEW.name); +END | +change_user regular,,; +INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +# same for DELETE because delete with "WHERE" still requires to +# read from the table, which basically means having select privileges +DELETE FROM test1.t_trigger_test1 WHERE id=1; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +DELETE FROM test1.t_trigger_test1 RETURNING *; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +DELETE FROM test1.t_trigger_test1 RETURNING id; +ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1' +DELETE FROM test1.t_trigger_test1; +change_user root,,; +DROP TRIGGER test1.trg_before_insert; +DROP TABLE test1.t_trigger_test1; +DROP USER regular; +DROP DATABASE test1; diff --git a/mysql-test/main/insert_notembedded.test b/mysql-test/main/insert_notembedded.test index 2769aee8d8a..09f5b18531d 100644 --- a/mysql-test/main/insert_notembedded.test +++ b/mysql-test/main/insert_notembedded.test @@ -158,3 +158,60 @@ DROP DATABASE meow; set local sql_mode=default; set global sql_mode=default; + +--echo # +--echo # MDEV-37950: INSERT ... RETURNING exposes columns for which +--echo # the user lacks SELECT privilege +--echo # +CREATE USER regular; +GRANT INSERT ON *.* TO regular; +GRANT DELETE ON *.* TO regular; + +CREATE DATABASE test1; +DROP TABLE IF EXISTS test1.t_trigger_test1; +CREATE TABLE test1.t_trigger_test1 ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(50), + note VARCHAR(100) +); +DELIMITER |; +CREATE TRIGGER test1.trg_before_insert +BEFORE INSERT ON test1.t_trigger_test1 +FOR EACH ROW +BEGIN + SET NEW.name = CONCAT('BEFORE_', NEW.name); +END | +DELIMITER ;| + +change_user regular; + +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *; +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note; + +--echo # same for DELETE because delete with "WHERE" still requires to +--echo # read from the table, which basically means having select privileges + +--error ER_COLUMNACCESS_DENIED_ERROR +DELETE FROM test1.t_trigger_test1 WHERE id=1; + +--error ER_COLUMNACCESS_DENIED_ERROR +DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id; + +--error ER_COLUMNACCESS_DENIED_ERROR +DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *; + +--error ER_COLUMNACCESS_DENIED_ERROR +DELETE FROM test1.t_trigger_test1 RETURNING *; + +--error ER_COLUMNACCESS_DENIED_ERROR +DELETE FROM test1.t_trigger_test1 RETURNING id; + +DELETE FROM test1.t_trigger_test1; + +change_user root; +DROP TRIGGER test1.trg_before_insert; +DROP TABLE test1.t_trigger_test1; +DROP USER regular; +DROP DATABASE test1; diff --git a/mysql-test/main/intersect_all.result b/mysql-test/main/intersect_all.result index 194b4cb9bcb..81a57414426 100644 --- a/mysql-test/main/intersect_all.result +++ b/mysql-test/main/intersect_all.result @@ -1094,23 +1094,31 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL set sql_mode= 'oracle'; explain SELECT * from t3 union select * from u3 intersect all select * from i3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 system NULL NULL NULL NULL 0 Const row not found -2 UNION u3 system NULL NULL NULL NULL 0 Const row not found -3 INTERSECT i3 system NULL NULL NULL NULL 0 Const row not found -NULL UNIT RESULT ALL NULL NULL NULL NULL NULL -select * from t3 union select * from u3 intersect select * from i3; +1 PRIMARY ALL NULL NULL NULL NULL 2 +4 DERIVED ALL NULL NULL NULL NULL 2 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +5 INTERSECT NULL NULL NULL NULL NULL NULL NULL no matching row in const table +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +select x from t3 union select x from u3 intersect select x from i3; x -SELECT * from t3 union select * from u3 intersect all select * from i3; +SELECT x from t3 union select x from u3 intersect all select x from i3; x insert into t3 values (0); insert into i3 values (0); -Select * from t3 union select * from u3 intersect select * from i3; +Select x from t3 union select x from u3 intersect select x from i3; x 0 -SELECT * FROM t3 UNION SELECT * FROM u3 INTERSECT ALL SELECT * FROM i3; +SELECT x FROM t3 UNION SELECT x FROM u3 INTERSECT ALL SELECT x FROM i3; +x +0 +create view v as select * from t3 union select * from u3 intersect select * from i3; +select * from v; x 0 drop tables t3, u3, i3; +drop view v; # First line of these results is column names, not the result # (pay attention to "affected rows") values (1, 2) union all values (1, 2); @@ -1136,10 +1144,47 @@ values (1, 2) union all values (1, 2) union values (4, 3) union all values (4, 3 1 2 4 3 affected rows: 2 +set sql_mode= default; create table t1 (a int, b int); create table t2 like t1; insert t1 values (1, 2), (1, 2), (1, 2), (2, 3), (2, 3), (3, 4), (3, 4); insert t2 values (1, 2), (1, 2), (2, 3), (2, 3), (2, 3), (2, 3), (4, 5); +select * from t1 intersect all select * from t2; +a b +1 2 +2 3 +1 2 +2 3 +select * from t1 intersect all select * from t2 union values (1, 2); +a b +1 2 +2 3 +select * from t1 intersect all (select * from t2 union values (1, 2)); +a b +1 2 +2 3 +(select * from t1 intersect all select * from t2) union values (1, 2); +a b +1 2 +2 3 +create view v1 as select * from t1 intersect all select * from t2 union values (1, 2); +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` intersect all select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` union values (1,2) latin1 latin1_swedish_ci +select * from v1; +a b +1 2 +2 3 +create view v2 as select * from t1 union values (1, 2) intersect all select * from t2; +show create view v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` union select `__5`.`1` AS `1`,`__5`.`2` AS `2` from (values (1,2) intersect all select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2`) `__5` latin1 latin1_swedish_ci +select * from v2; +a b +1 2 +2 3 +3 4 +set sql_mode= 'oracle'; select * from t1 intersect select * from t2; a b 1 2 @@ -1169,8 +1214,6 @@ select * from t1 intersect all select * from t2 union values (1, 2); a b 1 2 2 3 -1 2 -2 3 select * from t1 intersect all (select * from t2 union values (1, 2)); a b 1 2 @@ -1181,9 +1224,209 @@ a b 2 3 explain select * from t1 intersect all select * from t2 union values (1, 2); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 7 -2 INTERSECT t2 ALL NULL NULL NULL NULL 7 -3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used -NULL UNIT RESULT ALL NULL NULL NULL NULL NULL +1 PRIMARY ALL NULL NULL NULL NULL 8 +4 DERIVED ALL NULL NULL NULL NULL 7 +2 DERIVED t1 ALL NULL NULL NULL NULL 7 +3 INTERSECT t2 ALL NULL NULL NULL NULL 7 +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +5 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select "__6"."a" AS "a","__6"."b" AS "b" from (select "__4"."a" AS "a","__4"."b" AS "b" from (select "t1"."a" AS "a","t1"."b" AS "b" from "t1" intersect all select "t2"."a" AS "a","t2"."b" AS "b" from "t2") "__4" union values (1,2)) "__6" latin1 latin1_swedish_ci +select * from v1; +a b +1 2 +2 3 +show create view v2; +View Create View character_set_client collation_connection +v2 CREATE VIEW "v2" AS select "__7"."a" AS "a","__7"."b" AS "b" from (select "t1"."a" AS "a","t1"."b" AS "b" from "t1" union select "__5"."1" AS "1","__5"."2" AS "2" from (select "__6"."1" AS "1","__6"."2" AS "2" from (values (1,2) intersect all select "t2"."a" AS "a","t2"."b" AS "b" from "t2") "__6") "__5") "__7" latin1 latin1_swedish_ci +select * from v2; +a b +1 2 +2 3 +3 4 +create view v3 as select * from t1 union values (1, 2) intersect all select * from t2; +show create view v3; +View Create View character_set_client collation_connection +v3 CREATE VIEW "v3" AS select "__6"."a" AS "a","__6"."b" AS "b" from (select "__8"."a" AS "a","__8"."b" AS "b" from (select "__4"."a" AS "a","__4"."b" AS "b" from (select "__6"."a" AS "a","__6"."b" AS "b" from (select "t1"."a" AS "a","t1"."b" AS "b" from "t1" union values (1,2)) "__6") "__4" intersect all select "t2"."a" AS "a","t2"."b" AS "b" from "t2") "__8") "__6" latin1 latin1_swedish_ci +select * from v3; +a b +1 2 +2 3 drop tables t1, t2; +drop view v1, v2, v3; +create table t3 (x int); +create table u3 (x int); +create table i3 (x int); +create view v4 as SELECT * from t3 union select * from u3 intersect all select * from i3; +select * from v4; +x +drop tables t3, u3, i3; +drop view v4; +set sql_mode= default; +# +# MDEV-37325 Incorrect results for INTERSECT ALL in ORACLE mode +# +create table t1 (a int, b int); +create table t2 like t1; +insert t1 values (1, 2), (1, 2), (1, 2), (1, 2); +insert t2 values (1, 2), (1, 2); +select * from t1 except all select * from t2 intersect all values (1, 2); +a b +1 2 +1 2 +1 2 +explain select * from t1 except all select * from t2 intersect all values (1, 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +4 EXCEPT ALL NULL NULL NULL NULL 2 +2 DERIVED t2 ALL NULL NULL NULL NULL 2 +3 INTERSECT NULL NULL NULL NULL NULL NULL NULL No tables used +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +NULL EXCEPT RESULT ALL NULL NULL NULL NULL NULL +Explain select * from (select * from (select * from t1 except all select * from t2) __3 intersect all values (1,2)) __5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +2 DERIVED ALL NULL NULL NULL NULL 4 +3 DERIVED t1 ALL NULL NULL NULL NULL 4 +4 EXCEPT t2 ALL NULL NULL NULL NULL 2 +NULL EXCEPT RESULT ALL NULL NULL NULL NULL NULL +5 INTERSECT NULL NULL NULL NULL NULL NULL NULL No tables used +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +create view v1 as select * from t1 except all select * from t2 intersect all values (1, 2); +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` except all select `__5`.`a` AS `a`,`__5`.`b` AS `b` from (select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` intersect all values (1,2)) `__5` latin1 latin1_swedish_ci +select * from v1; +a b +1 2 +1 2 +1 2 +drop view v1; +create view v1 as ((select * from t1 except all select * from t2) intersect all values (1, 2)); +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__5`.`a` AS `a`,`__5`.`b` AS `b` from (select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` except all select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2`) `__5` intersect all values (1,2) latin1 latin1_swedish_ci +select * from v1; +a b +1 2 +drop view v1; +explain select * from ((select * from t1 except all select * from t2) intersect all values (1, 2)) v; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +5 DERIVED ALL NULL NULL NULL NULL 4 +2 DERIVED t1 ALL NULL NULL NULL NULL 4 +3 EXCEPT t2 ALL NULL NULL NULL NULL 2 +NULL EXCEPT RESULT ALL NULL NULL NULL NULL NULL +4 INTERSECT NULL NULL NULL NULL NULL NULL NULL No tables used +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +# Oracle: first UNION, then INTERSECT ALL +set sql_mode= 'oracle'; +create view v2 as select * from t1 except all select * from t2 intersect all values (1, 2); +show create view v2; +View Create View character_set_client collation_connection +v2 CREATE VIEW "v2" AS select "__6"."a" AS "a","__6"."b" AS "b" from (select "__8"."a" AS "a","__8"."b" AS "b" from (select "__4"."a" AS "a","__4"."b" AS "b" from (select "__6"."a" AS "a","__6"."b" AS "b" from (select "t1"."a" AS "a","t1"."b" AS "b" from "t1" except all select "t2"."a" AS "a","t2"."b" AS "b" from "t2") "__6") "__4" intersect all values (1,2)) "__8") "__6" latin1 latin1_swedish_ci +select * from v2; +a b +1 2 +drop view v2; +EXPLAIN select * from t1 except all select * from t2 intersect all values (1, 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +4 DERIVED ALL NULL NULL NULL NULL 4 +2 DERIVED t1 ALL NULL NULL NULL NULL 4 +3 EXCEPT t2 ALL NULL NULL NULL NULL 2 +NULL EXCEPT RESULT ALL NULL NULL NULL NULL NULL +5 INTERSECT NULL NULL NULL NULL NULL NULL NULL No tables used +NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL +select * from t2 union all select * from t2; +a b +1 2 +1 2 +1 2 +1 2 +select * from t1 except all select * from t2 intersect all values (1, 2) union values (2, 3); +a b +1 2 +2 3 +select * from t2 union all select * from t2 except all select * from t2 intersect all values (1, 2) union values (2, 3); +a b +1 2 +2 3 +select * from t1 except all select * from t2 union values (2, 3); +a b +1 2 +2 3 +# Default: first INTERSECT ALL, then UNION +select * from t1 union values (1, 2) intersect all select * from t2; +a b +1 2 +select * from t1 union (values (1, 2) intersect all select * from t2); +a b +1 2 +set sql_mode= default; +select * from t1 union values (1, 2) intersect all select * from t2; +a b +1 2 +select * from t1 union (values (1, 2) intersect all select * from t2); +a b +1 2 +set sql_mode= 'oracle'; +create or replace table t2 like t1; +insert t2 values (1, 2), (2, 3); +create table t3 select * from t1 except all select * from t2; +select * from t3; +a b +1 2 +1 2 +1 2 +select * from t3 intersect all select * from t1; +a b +1 2 +1 2 +1 2 +show create table t2; +Table Create Table +t2 CREATE TABLE "t2" ( + "a" int(11) DEFAULT NULL, + "b" int(11) DEFAULT NULL +) +select * from t2 order by a desc; +a b +2 3 +1 2 +select * from t1 except all select * from t2; +a b +1 2 +1 2 +1 2 +select * from t1 except all select * from t2 union all values (0, 1); +a b +1 2 +1 2 +1 2 +0 1 +select * from t1 except all select * from t2 union all values (0, 1) order by a limit 2; +a b +0 1 +1 2 +select * from t1 except all select * from t2 intersect all select * from t1; +a b +1 2 +1 2 +1 2 +select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2; +a b +1 2 +1 2 +1 2 +1 2 +2 3 +select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2 order by a desc limit 3; +a b +2 3 +1 2 +1 2 +drop tables t1, t2, t3; set sql_mode= default; diff --git a/mysql-test/main/intersect_all.test b/mysql-test/main/intersect_all.test index b318914fe8c..6ac8df4be14 100644 --- a/mysql-test/main/intersect_all.test +++ b/mysql-test/main/intersect_all.test @@ -338,13 +338,22 @@ create table i3 (x int); explain SELECT * from t3 union select * from u3 intersect all select * from i3; set sql_mode= 'oracle'; explain SELECT * from t3 union select * from u3 intersect all select * from i3; +# TODO: there is a bug in --view protocol, it displays column name as '*' instead of 'x' +--replace_result * x select * from t3 union select * from u3 intersect select * from i3; +--replace_result * x SELECT * from t3 union select * from u3 intersect all select * from i3; insert into t3 values (0); insert into i3 values (0); +--replace_result * x Select * from t3 union select * from u3 intersect select * from i3; +--replace_result * x SELECT * FROM t3 UNION SELECT * FROM u3 INTERSECT ALL SELECT * FROM i3; +# CREATE VIEW still works good +create view v as select * from t3 union select * from u3 intersect select * from i3; +select * from v; drop tables t3, u3, i3; +drop view v; --enable_info --echo # First line of these results is column names, not the result @@ -374,10 +383,26 @@ values (1, 2) union all values (1, 2) union values (4, 3) union all values (4, 3 values (1, 2) union all values (1, 2) union values (4, 3) union all values (4, 3) union all values (1, 2) union values (1, 2); --disable_info +set sql_mode= default; create table t1 (a int, b int); create table t2 like t1; insert t1 values (1, 2), (1, 2), (1, 2), (2, 3), (2, 3), (3, 4), (3, 4); insert t2 values (1, 2), (1, 2), (2, 3), (2, 3), (2, 3), (2, 3), (4, 5); + +select * from t1 intersect all select * from t2; +select * from t1 intersect all select * from t2 union values (1, 2); +select * from t1 intersect all (select * from t2 union values (1, 2)); +(select * from t1 intersect all select * from t2) union values (1, 2); + +create view v1 as select * from t1 intersect all select * from t2 union values (1, 2); +show create view v1; +select * from v1; + +create view v2 as select * from t1 union values (1, 2) intersect all select * from t2; +show create view v2; +select * from v2; + +set sql_mode= 'oracle'; select * from t1 intersect select * from t2; select * from t1 intersect all select * from t2; --echo # Default: first INTERSECT ALL, then UNION @@ -392,5 +417,85 @@ select * from t1 intersect all select * from t2 union values (1, 2); select * from t1 intersect all (select * from t2 union values (1, 2)); (select * from t1 intersect all select * from t2) union values (1, 2); explain select * from t1 intersect all select * from t2 union values (1, 2); + +show create view v1; +select * from v1; + +show create view v2; +select * from v2; + +create view v3 as select * from t1 union values (1, 2) intersect all select * from t2; +show create view v3; +select * from v3; + drop tables t1, t2; +drop view v1, v2, v3; + +create table t3 (x int); +create table u3 (x int); +create table i3 (x int); +create view v4 as SELECT * from t3 union select * from u3 intersect all select * from i3; +select * from v4; +drop tables t3, u3, i3; +drop view v4; +set sql_mode= default; + +--echo # +--echo # MDEV-37325 Incorrect results for INTERSECT ALL in ORACLE mode +--echo # +create table t1 (a int, b int); +create table t2 like t1; +insert t1 values (1, 2), (1, 2), (1, 2), (1, 2); +insert t2 values (1, 2), (1, 2); +select * from t1 except all select * from t2 intersect all values (1, 2); +explain select * from t1 except all select * from t2 intersect all values (1, 2); +Explain select * from (select * from (select * from t1 except all select * from t2) __3 intersect all values (1,2)) __5; + +create view v1 as select * from t1 except all select * from t2 intersect all values (1, 2); +show create view v1; +select * from v1; +drop view v1; + +create view v1 as ((select * from t1 except all select * from t2) intersect all values (1, 2)); +show create view v1; +select * from v1; +drop view v1; + +explain select * from ((select * from t1 except all select * from t2) intersect all values (1, 2)) v; + +--echo # Oracle: first UNION, then INTERSECT ALL +set sql_mode= 'oracle'; +create view v2 as select * from t1 except all select * from t2 intersect all values (1, 2); +show create view v2; +select * from v2; +drop view v2; + +EXPLAIN select * from t1 except all select * from t2 intersect all values (1, 2); + +select * from t2 union all select * from t2; +select * from t1 except all select * from t2 intersect all values (1, 2) union values (2, 3); +select * from t2 union all select * from t2 except all select * from t2 intersect all values (1, 2) union values (2, 3); +select * from t1 except all select * from t2 union values (2, 3); +--echo # Default: first INTERSECT ALL, then UNION +select * from t1 union values (1, 2) intersect all select * from t2; +select * from t1 union (values (1, 2) intersect all select * from t2); +set sql_mode= default; +select * from t1 union values (1, 2) intersect all select * from t2; +select * from t1 union (values (1, 2) intersect all select * from t2); + +set sql_mode= 'oracle'; +create or replace table t2 like t1; +insert t2 values (1, 2), (2, 3); +create table t3 select * from t1 except all select * from t2; +select * from t3; +select * from t3 intersect all select * from t1; +show create table t2; +select * from t2 order by a desc; +select * from t1 except all select * from t2; +select * from t1 except all select * from t2 union all values (0, 1); +select * from t1 except all select * from t2 union all values (0, 1) order by a limit 2; +select * from t1 except all select * from t2 intersect all select * from t1; +select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2; +select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2 order by a desc limit 3; +drop tables t1, t2, t3; set sql_mode= default; diff --git a/mysql-test/main/kill-2.result b/mysql-test/main/kill-2.result index c16367930d3..543ad4bdb4a 100644 --- a/mysql-test/main/kill-2.result +++ b/mysql-test/main/kill-2.result @@ -4,10 +4,9 @@ create user foo@'127.0.0.1'; connect con1,127.0.0.1,foo,,; connection default; -select user from information_schema.processlist; +select user from information_schema.processlist where id=$con1_id; user foo -root kill user foo@'127.0.0.1'; drop user foo@'127.0.0.1'; # @@ -28,11 +27,11 @@ Id User Host db Command Time State Info Progress kill user a; kill user x; connection a; -show processlist; -Id User Host db Command Time State Info Progress -# root # test # # # # # -# a # NULL # # # # # -# b # test # # # # # +select user from information_schema.processlist where id in (connection_id(), $b_id, $default_id) order by user; +user +a +b +root kill user b; ERROR HY000: Operation KILL USER failed for b@% connection default; diff --git a/mysql-test/main/kill-2.test b/mysql-test/main/kill-2.test index 69fccaa0c27..fee81a63906 100644 --- a/mysql-test/main/kill-2.test +++ b/mysql-test/main/kill-2.test @@ -16,9 +16,10 @@ create user foo@'127.0.0.1'; --connect (con1,127.0.0.1,foo,,) +let $con1_id= `select connection_id()`; --connection default -select user from information_schema.processlist; +evalp select user from information_schema.processlist where id=$con1_id; kill user foo@'127.0.0.1'; let $wait_condition= @@ -31,6 +32,7 @@ drop user foo@'127.0.0.1'; --echo # --echo # KILL USER and missing privileges --echo # +let $default_id= `select connection_id()`; create user a@'127.0.0.1'; create user b@'127.0.0.1'; grant process on *.* to a@'127.0.0.1'; @@ -38,13 +40,13 @@ grant select on *.* to b@'127.0.0.1'; --connect a,127.0.0.1,a show grants; --connect b,127.0.0.1,b +let $b_id= `select connection_id()`; --replace_column 1 # 3 # 5 # 6 # 9 # show processlist; kill user a; # existing connection, but not visible to current_user kill user x; # not existing connection --connection a ---replace_column 1 # 3 # 5 # 6 # 7 # 8 # 9 # -show processlist; +evalp select user from information_schema.processlist where id in (connection_id(), $b_id, $default_id) order by user; --error ER_KILL_DENIED_ERROR kill user b; --connection default diff --git a/mysql-test/main/max_session_mem_used.result b/mysql-test/main/max_session_mem_used.result index 457dc84a86b..90c6bbb45eb 100644 --- a/mysql-test/main/max_session_mem_used.result +++ b/mysql-test/main/max_session_mem_used.result @@ -45,6 +45,15 @@ REPAIR LOCAL TABLE t1 USE_FRM; REPAIR LOCAL TABLE t1; DROP TABLE t1; SET max_session_mem_used=default; +# +# MDEV-38005 Assertion `(yyvsp[-3].simple_string) < (yyvsp[-1].simple_string)' failed +# +SET max_session_mem_used=1; +Warnings: +Warning 1292 Truncated incorrect max_session_mem_used value: '1' +CREATE TABLE t SELECT 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 AS c; +ERROR HY000: The MariaDB server is running with the --max-session-mem-used=8192 option so it cannot execute this statement +SET max_session_mem_used=default; # End of 10.6 tests # # MDEV-37489: SIGSEGV in get_param_default_value | store_schema_params diff --git a/mysql-test/main/max_session_mem_used.test b/mysql-test/main/max_session_mem_used.test index 9c4a0b569ca..d05c05b9987 100644 --- a/mysql-test/main/max_session_mem_used.test +++ b/mysql-test/main/max_session_mem_used.test @@ -83,6 +83,14 @@ REPAIR LOCAL TABLE t1; DROP TABLE t1; SET max_session_mem_used=default; +--echo # +--echo # MDEV-38005 Assertion `(yyvsp[-3].simple_string) < (yyvsp[-1].simple_string)' failed +--echo # +SET max_session_mem_used=1; +--error ER_OPTION_PREVENTS_STATEMENT +CREATE TABLE t SELECT 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 AS c; +SET max_session_mem_used=default; + --echo # End of 10.6 tests --echo # diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result index 18e5c8718dc..ba3b9cd8a8f 100644 --- a/mysql-test/main/mysql_client_test.result +++ b/mysql-test/main/mysql_client_test.result @@ -262,3 +262,9 @@ SET @@global.collation_server= @save_collation_server; SET @@global.character_set_client= @save_character_set_client; SET @@global.collation_connection= @save_collation_connection; FOUND 1 /Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)'/ in mysqld.1.err +# +# MDEV-36269: Improve error handling for SOURCE command +# Test that SOURCE on an existent directory returns a clear error +# +ERROR at line 1: Can't read from a directory '.' +End of 10.11 tests diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test index d620f4c7078..f99aecace80 100644 --- a/mysql-test/main/mysql_client_test.test +++ b/mysql-test/main/mysql_client_test.test @@ -63,3 +63,13 @@ SET @@global.collation_connection= @save_collation_connection; let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err; let SEARCH_PATTERN= Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)'; source include/search_pattern_in_file.inc; + +--echo # +--echo # MDEV-36269: Improve error handling for SOURCE command +--echo # Test that SOURCE on an existent directory returns a clear error +--echo # + +--error 1 +--exec $MYSQL -e "source ." 2>&1 + +--echo End of 10.11 tests diff --git a/mysql-test/main/old-mode.test b/mysql-test/main/old-mode.test index cc44423d957..74a6b7c7bf0 100644 --- a/mysql-test/main/old-mode.test +++ b/mysql-test/main/old-mode.test @@ -14,6 +14,8 @@ drop table t1,t2; # # Test that SHOW PROCESSLIST doesn't have the Progress column # +let $count_sessions= 1; +source include/wait_until_count_sessions.inc; --replace_column 1 3 6