diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-11-09 12:27:54 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-11-09 12:27:54 +0200 |
commit | 27eaa963ff18d12939f798a78720d73cf6ce0b5d (patch) | |
tree | 0bca93e0e81c308a3497b7ff59b97d03202cb863 | |
parent | 320de65135c6dd1af7c2f34ac0469b80aaf3ddb6 (diff) | |
parent | e56c12b3cdf57ad29cee0ffe33bd6bc44c963789 (diff) | |
download | mariadb-git-27eaa963ff18d12939f798a78720d73cf6ce0b5d.tar.gz |
Merge 10.6 into 10.7
75 files changed, 1001 insertions, 990 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 46613fc1333..0ed5a62c1a4 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1748,7 +1748,8 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename) len= (size_t) my_seek(fd, 0, SEEK_END, MYF(0)); my_seek(fd, 0, SEEK_SET, MYF(0)); if (len == (size_t)MY_FILEPOS_ERROR || - !(buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, len + 1, MYF(0)))) + !(buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, len + 1, + MYF(MY_WME|MY_FAE)))) { my_close(fd, MYF(0)); return 1; @@ -2407,7 +2408,7 @@ VAR *var_init(VAR *v, const char *name, size_t name_len, const char *val, size_t val_len= 0; val_alloc_len = val_len + 16; /* room to grow */ if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*tmp_var) - + name_len+2, MYF(MY_WME)))) + + name_len+2, MYF(MY_WME|MY_FAE)))) die("Out of memory"); if (name != NULL) @@ -2421,7 +2422,8 @@ VAR *var_init(VAR *v, const char *name, size_t name_len, const char *val, size_t tmp_var->alloced = (v == 0); - if (!(tmp_var->str_val = (char*)my_malloc(PSI_NOT_INSTRUMENTED, val_alloc_len+1, MYF(MY_WME)))) + if (!(tmp_var->str_val = (char*)my_malloc(PSI_NOT_INSTRUMENTED, + val_alloc_len+1, MYF(MY_WME|MY_FAE)))) die("Out of memory"); if (val) @@ -2969,8 +2971,10 @@ void var_copy(VAR *dest, VAR *src) /* Alloc/realloc data for str_val in dest */ if (dest->alloced_len < src->alloced_len && !(dest->str_val= dest->str_val - ? (char*)my_realloc(PSI_NOT_INSTRUMENTED, dest->str_val, src->alloced_len, MYF(MY_WME)) - : (char*)my_malloc(PSI_NOT_INSTRUMENTED, src->alloced_len, MYF(MY_WME)))) + ? (char*)my_realloc(PSI_NOT_INSTRUMENTED, dest->str_val, src->alloced_len, + MYF(MY_WME|MY_FAE)) + : (char*)my_malloc(PSI_NOT_INSTRUMENTED, src->alloced_len, + MYF(MY_WME|MY_FAE)))) die("Out of memory"); else dest->alloced_len= src->alloced_len; @@ -3047,8 +3051,10 @@ void eval_expr(VAR *v, const char *p, const char **p_end, MIN_VAR_ALLOC : new_val_len + 1; if (!(v->str_val = v->str_val ? - (char*)my_realloc(PSI_NOT_INSTRUMENTED, v->str_val, v->alloced_len+1, MYF(MY_WME)) : - (char*)my_malloc(PSI_NOT_INSTRUMENTED, v->alloced_len+1, MYF(MY_WME)))) + (char*)my_realloc(PSI_NOT_INSTRUMENTED, v->str_val, v->alloced_len+1, + MYF(MY_WME|MY_FAE)) : + (char*)my_malloc(PSI_NOT_INSTRUMENTED, v->alloced_len+1, + MYF(MY_WME|MY_FAE)))) die("Out of memory"); } v->str_val_len = new_val_len; @@ -4783,7 +4789,8 @@ void do_sync_with_master(struct st_command *command) p++; while (*p && my_isspace(charset_info, *p)) p++; - start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,MYF(MY_WME | MY_FAE)); + start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1, + MYF(MY_WME|MY_FAE)); get_string(&buff, &p, command); } command->last_argument= p; @@ -6923,7 +6930,7 @@ int read_command(struct st_command** command_ptr) } if (!(*command_ptr= command= (struct st_command*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*command), - MYF(MY_WME|MY_ZEROFILL))) || + MYF(MY_WME|MY_FAE|MY_ZEROFILL))) || insert_dynamic(&q_lines, &command)) die("Out of memory"); command->type= Q_UNKNOWN; @@ -7631,18 +7638,19 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, /* Allocate array with bind structs, lengths and NULL flags */ my_bind= (MYSQL_BIND*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(MYSQL_BIND), - MYF(MY_WME | MY_FAE | MY_ZEROFILL)); + MYF(MY_WME|MY_FAE|MY_ZEROFILL)); length= (ulong*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(ulong), - MYF(MY_WME | MY_FAE)); + MYF(MY_WME|MY_FAE)); is_null= (my_bool*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(my_bool), - MYF(MY_WME | MY_FAE)); + MYF(MY_WME|MY_FAE)); /* Allocate data for the result of each field */ for (i= 0; i < num_fields; i++) { uint max_length= fields[i].max_length + 1; my_bind[i].buffer_type= MYSQL_TYPE_STRING; - my_bind[i].buffer= my_malloc(PSI_NOT_INSTRUMENTED, max_length, MYF(MY_WME | MY_FAE)); + my_bind[i].buffer= my_malloc(PSI_NOT_INSTRUMENTED, max_length, + MYF(MY_WME|MY_FAE)); my_bind[i].buffer_length= max_length; my_bind[i].is_null= &is_null[i]; my_bind[i].length= &length[i]; @@ -8666,7 +8674,7 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, cn->ps_params= ps_params = (MYSQL_BIND*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(MYSQL_BIND) * stmt->param_count, - MYF(MY_WME)); + MYF(MY_WME|MY_FAE)); bzero((char *) ps_params, sizeof(MYSQL_BIND) * stmt->param_count); int i=0; @@ -8681,7 +8689,8 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, if (!*c) { ps_params[i].buffer_type= MYSQL_TYPE_LONG; - l= (long*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(long), MYF(MY_WME)); + l= (long*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(long), + MYF(MY_WME|MY_FAE)); *l= strtol(p, &c, 10); ps_params[i].buffer= (void*)l; ps_params[i].buffer_length= 8; @@ -8693,7 +8702,7 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, { ps_params[i].buffer_type= MYSQL_TYPE_DECIMAL; d= (double*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(double), - MYF(MY_WME)); + MYF(MY_WME|MY_FAE)); *d= strtod(p, &c); ps_params[i].buffer= (void*)d; ps_params[i].buffer_length= 8; @@ -8701,7 +8710,8 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, else { ps_params[i].buffer_type= MYSQL_TYPE_STRING; - ps_params[i].buffer= my_strdup(PSI_NOT_INSTRUMENTED, p, MYF(MY_WME)); + ps_params[i].buffer= my_strdup(PSI_NOT_INSTRUMENTED, p, + MYF(MY_WME|MY_FAE)); ps_params[i].buffer_length= (unsigned long)strlen(p); } } @@ -9739,7 +9749,7 @@ int main(int argc, char **argv) /* Init connections, allocate 1 extra as buffer + 1 for default */ connections= (struct st_connection*) my_malloc(PSI_NOT_INSTRUMENTED, (opt_max_connections+2) * sizeof(struct st_connection), - MYF(MY_WME | MY_ZEROFILL)); + MYF(MY_WME|MY_FAE|MY_ZEROFILL)); connections_end= connections + opt_max_connections +1; next_con= connections + 1; @@ -10461,7 +10471,8 @@ void do_get_replace_column(struct st_command *command) die("Missing argument in %s", command->query); /* Allocate a buffer for results */ - start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(from)+1,MYF(MY_WME | MY_FAE)); + start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(from)+1, + MYF(MY_WME|MY_FAE)); while (*from) { char *to; @@ -10474,7 +10485,8 @@ void do_get_replace_column(struct st_command *command) command->query); to= get_string(&buff, &from, command); my_free(replace_column[column_number-1]); - replace_column[column_number-1]= my_strdup(PSI_NOT_INSTRUMENTED, to, MYF(MY_WME | MY_FAE)); + replace_column[column_number-1]= my_strdup(PSI_NOT_INSTRUMENTED, to, + MYF(MY_WME|MY_FAE)); set_if_bigger(max_replace_column, column_number); } my_free(start); @@ -10541,7 +10553,8 @@ void do_get_replace(struct st_command *command) bzero(&from_array,sizeof(from_array)); if (!*from) die("Missing argument in %s", command->query); - start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(from)+1,MYF(MY_WME | MY_FAE)); + start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(from)+1, + MYF(MY_WME|MY_FAE)); while (*from) { char *to= buff; @@ -11199,7 +11212,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count, DBUG_RETURN(0); found_sets=0; if (!(found_set= (FOUND_SET*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(FOUND_SET)*max_length*count, - MYF(MY_WME)))) + MYF(MY_WME|MY_FAE)))) { free_sets(&sets); DBUG_RETURN(0); @@ -11209,7 +11222,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count, used_sets=-1; word_states=make_new_set(&sets); /* Start of new word */ start_states=make_new_set(&sets); /* This is first state */ - if (!(follow=(FOLLOWS*) my_malloc(PSI_NOT_INSTRUMENTED, (states+2)*sizeof(FOLLOWS),MYF(MY_WME)))) + if (!(follow=(FOLLOWS*) my_malloc(PSI_NOT_INSTRUMENTED, (states+2)*sizeof(FOLLOWS),MYF(MY_WME|MY_FAE)))) { free_sets(&sets); my_free(found_set); @@ -11376,7 +11389,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count, if ((replace=(REPLACE*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(REPLACE)*(sets.count)+ sizeof(REPLACE_STRING)*(found_sets+1)+ sizeof(char *)*count+result_len, - MYF(MY_WME | MY_ZEROFILL)))) + MYF(MY_WME|MY_FAE|MY_ZEROFILL)))) { rep_str=(REPLACE_STRING*) (replace+sets.count); to_array= (char **) (rep_str+found_sets+1); @@ -11419,10 +11432,10 @@ int init_sets(REP_SETS *sets,uint states) bzero(sets, sizeof(*sets)); sets->size_of_bits=((states+7)/8); if (!(sets->set_buffer=(REP_SET*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(REP_SET)*SET_MALLOC_HUNC, - MYF(MY_WME)))) + MYF(MY_WME|MY_FAE)))) return 1; if (!(sets->bit_buffer=(uint*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(uint)*sets->size_of_bits* - SET_MALLOC_HUNC,MYF(MY_WME)))) + SET_MALLOC_HUNC,MYF(MY_WME|MY_FAE)))) { my_free(sets->set); return 1; @@ -11618,10 +11631,10 @@ int insert_pointer_name(POINTER_ARRAY *pa,char * name) if (!(pa->typelib.type_names=(const char **) my_malloc(PSI_NOT_INSTRUMENTED, ((PC_MALLOC-MALLOC_OVERHEAD)/ (sizeof(char *)+sizeof(*pa->flag))* - (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME)))) + (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME|MY_FAE)))) DBUG_RETURN(-1); if (!(pa->str= (uchar*) my_malloc(PSI_NOT_INSTRUMENTED, PS_MALLOC - MALLOC_OVERHEAD, - MYF(MY_WME)))) + MYF(MY_WME|MY_FAE)))) { my_free(pa->typelib.type_names); DBUG_RETURN (-1); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index ed68a96004d..88fd213f8a2 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3818,10 +3818,6 @@ static dberr_t xb_assign_undo_space_start() uint32_t fsp_flags; int n_retries = 5; - if (srv_undo_tablespaces == 0) { - return error; - } - file = os_file_create(0, srv_sys_space.first_datafile()->filepath(), OS_FILE_OPEN, OS_FILE_NORMAL, OS_DATA_FILE, true, &ret); diff --git a/include/my_alarm.h b/include/my_alarm.h index df5cb7f51de..652b460cba3 100644 --- a/include/my_alarm.h +++ b/include/my_alarm.h @@ -31,7 +31,10 @@ extern ulong my_time_to_wait_for_lock; #include <signal.h> #ifdef HAVE_SIGHANDLER_T #define sig_return sighandler_t -#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || defined(__FreeBSD__) || defined(_AIX) +#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || \ + defined(_AIX) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__DragonFly__) typedef void (*sig_return)(int); /* Returns type from signal */ #else typedef void (*sig_return)(void); /* Returns type from signal */ diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index 48be990964d..7be1d36fe55 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -340,7 +340,9 @@ program to set the server\'s scheduling priority to the given value\&. .\} .\" mysqld_safe: no-auto-restart option .\" no-auto-restart option: mysqld_safe -\fB\-\-no\-auto\-restart\fR +\fB\-\-no\-auto\-restart\fR, +\fB\-\-nowatch\fR, +\fB\-\-no\-watch\fR .sp Exit after starting mysqld\&. .RE @@ -368,21 +370,6 @@ Do not read any option files\&. This must be the first option on the command lin .sp -1 .IP \(bu 2.3 .\} -.\" mysqld_safe: no-watch option -.\" no-watch option: mysqld_safe -\fB\-\-no\-auto\-restart\fR -.sp -Exit after starting mysqld\&. -.RE -.sp -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.sp -1 -.IP \(bu 2.3 -.\} .\" mysqld_safe: numa-interleave option .\" numa-interleave option: mysqld_safe \fB\-\-numa\-interleave\fR diff --git a/mysql-test/include/rowid_filter_debug_kill.inc b/mysql-test/include/rowid_filter_debug_kill.inc index c701d206297..513efed8a4c 100644 --- a/mysql-test/include/rowid_filter_debug_kill.inc +++ b/mysql-test/include/rowid_filter_debug_kill.inc @@ -1,17 +1,14 @@ --source include/have_debug.inc --source include/have_debug_sync.inc +--source include/have_sequence.inc --source include/count_sessions.inc --echo # --echo # MDEV-22761 KILL QUERY during rowid_filter, crashes --echo # -create table t0(a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); - -# 100 rows create table t2(a int); -insert into t2 select A.a + B.a* 10 from t0 A, t0 B; +insert into t2 select * from seq_0_to_99; # 10K rows CREATE TABLE t3 ( @@ -26,11 +23,10 @@ where table_schema=database() and table_name='t3'; insert into t3 select - A.a, - B.a, + A.seq, + B.seq, 'filler-data-filler-data' -from - t2 A, t2 B; +from seq_0_to_99 A, seq_0_to_99 B; analyze table t2,t3; @@ -48,7 +44,6 @@ where t3.key1=t2.a and t3.key2 in (2,3); connect (con1, localhost, root,,); -connection con1; set debug_sync='now WAIT_FOR at_rowid_filter_check'; evalp kill query $target_id; set debug_sync='now SIGNAL go'; @@ -60,6 +55,5 @@ disconnect con1; reap; set debug_sync='RESET'; -drop table t0,t2,t3; +drop table t2,t3; --source include/wait_until_count_sessions.inc - diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 31fa5f8c8d5..4c2fbcf1dd6 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -317,6 +317,15 @@ ERROR 23000: Duplicate entry '1' for key 'v2' update t1,t2 set v1 = v2 , v5 = 0; ERROR 23000: Duplicate entry '-128' for key 'v1' drop table t1, t2; +CREATE TABLE t1 (f TEXT UNIQUE); +INSERT INTO t1 VALUES (NULL),(NULL); +UPDATE t1 SET f = ''; +ERROR 23000: Duplicate entry '' for key 'f' +SELECT * FROM t1; +f + +NULL +DROP TABLE t1; # # MDEV-21540 Initialization of already inited long unique index on reorganize partition # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 18e430858b0..8d1accd6cd3 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -397,6 +397,17 @@ update t1 set v2 = 1, v3 = -128; update t1,t2 set v1 = v2 , v5 = 0; drop table t1, t2; +# +# MDEV-23264 Unique blobs allow duplicate values upon UPDATE +# + +CREATE TABLE t1 (f TEXT UNIQUE); +INSERT INTO t1 VALUES (NULL),(NULL); +--error ER_DUP_ENTRY +UPDATE t1 SET f = ''; +SELECT * FROM t1; +DROP TABLE t1; + --echo # --echo # MDEV-21540 Initialization of already inited long unique index on reorganize partition --echo # diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 34af8eb6466..b6160bd3525 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -1319,10 +1319,6 @@ partition p2008 values less than (2009) ); select length(table_name) from mysql.innodb_table_stats; length(table_name) -79 -79 -79 -79 drop table extralongname_extralongname_extralongname_extralongname_ext; # End of 10.0 tests set sql_mode=default; diff --git a/mysql-test/main/order_by_innodb.result b/mysql-test/main/order_by_innodb.result index 28922ef65f2..17d39eb12e6 100644 --- a/mysql-test/main/order_by_innodb.result +++ b/mysql-test/main/order_by_innodb.result @@ -1,8 +1,8 @@ -drop table if exists t0,t1,t2,t3; # # MDEV-6434: Wrong result (extra rows) with ORDER BY, multiple-column index, InnoDB # -CREATE TABLE t1 (a INT, b INT, c INT, d TEXT, KEY idx(a,b,c)) ENGINE=InnoDB; +CREATE TABLE t1 (a INT, b INT, c INT, d TEXT, KEY idx(a,b,c)) ENGINE=InnoDB +STATS_PERSISTENT=0; INSERT INTO t1 (a,c) VALUES (8, 9),(8, 10),(13, 15),(16, 17),(16, 18),(16, 19),(20, 21), (20, 22),(20, 24),(20, 25),(20, 26),(20, 27),(20, 28); @@ -14,8 +14,6 @@ DROP TABLE t1; # # MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1 # -create table t0 (a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 ( pk int primary key, key1 int, @@ -23,15 +21,9 @@ key2 int, col1 char(255), key(key1), key(key2) -) engine=innodb; -set @a=-1; +) engine=innodb stats_persistent=0; insert into t1 -select -@a:=@a+1, -@a, -@a, -repeat('abcd', 63) -from t0 A, t0 B, t0 C, t0 D; +select seq,seq,seq,repeat('abcd', 63) from seq_0_to_9999; # The following must NOT use 'index' on PK. # It should use index_merge(key1,key2) + filesort explain @@ -47,7 +39,7 @@ from t1 where key1<3 or key2<3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where -drop table t0, t1; +drop table t1; # # MDEV-18094: Query with order by limit picking index scan over filesort # @@ -78,9 +70,12 @@ drop table t1,t0; # MDEV-14071: wrong results with orderby_uses_equalities=on # (duplicate of MDEV-13994) # -CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB; -CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB; -CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB; +CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB +STATS_PERSISTENT=0; +CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB +STATS_PERSISTENT=0; +CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB +STATS_PERSISTENT=0; INSERT INTO t1 VALUES (127,0,1),(188,0,1),(206,0,1),(218,0,1),(292,0,1),(338,0,1),(375,0,1), (381,0,1),(409,0,1),(466,0,1),(469,0,1),(498,0,1),(656,0,1); @@ -150,7 +145,8 @@ DROP TABLE t1,t2,t3; # # MDEV-25858: Query results are incorrect when indexes are added # -CREATE TABLE t1 (id int NOT NULL PRIMARY KEY) engine=innodb; +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY) engine=innodb +STATS_PERSISTENT=0; insert into t1 values (1),(2),(3); CREATE TABLE t2 ( id int NOT NULL PRIMARY KEY, diff --git a/mysql-test/main/order_by_innodb.test b/mysql-test/main/order_by_innodb.test index af12644c073..29b796f67bc 100644 --- a/mysql-test/main/order_by_innodb.test +++ b/mysql-test/main/order_by_innodb.test @@ -2,16 +2,14 @@ # ORDER BY handling (e.g. filesort) tests that require innodb # -- source include/have_innodb.inc - ---disable_warnings -drop table if exists t0,t1,t2,t3; ---enable_warnings +-- source include/have_sequence.inc --echo # --echo # MDEV-6434: Wrong result (extra rows) with ORDER BY, multiple-column index, InnoDB --echo # -CREATE TABLE t1 (a INT, b INT, c INT, d TEXT, KEY idx(a,b,c)) ENGINE=InnoDB; +CREATE TABLE t1 (a INT, b INT, c INT, d TEXT, KEY idx(a,b,c)) ENGINE=InnoDB +STATS_PERSISTENT=0; INSERT INTO t1 (a,c) VALUES (8, 9),(8, 10),(13, 15),(16, 17),(16, 18),(16, 19),(20, 21), @@ -24,9 +22,6 @@ DROP TABLE t1; --echo # --echo # MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1 --echo # -create table t0 (a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); - create table t1 ( pk int primary key, key1 int, @@ -34,16 +29,10 @@ create table t1 ( col1 char(255), key(key1), key(key2) -) engine=innodb; +) engine=innodb stats_persistent=0; -set @a=-1; insert into t1 -select - @a:=@a+1, - @a, - @a, - repeat('abcd', 63) -from t0 A, t0 B, t0 C, t0 D; +select seq,seq,seq,repeat('abcd', 63) from seq_0_to_9999; --echo # The following must NOT use 'index' on PK. --echo # It should use index_merge(key1,key2) + filesort @@ -60,7 +49,7 @@ select * from t1 where key1<3 or key2<3; -drop table t0, t1; +drop table t1; --echo # --echo # MDEV-18094: Query with order by limit picking index scan over filesort @@ -93,9 +82,12 @@ drop table t1,t0; --echo # (duplicate of MDEV-13994) --echo # -CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB; -CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB; -CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB; +CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB +STATS_PERSISTENT=0; +CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB +STATS_PERSISTENT=0; +CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB +STATS_PERSISTENT=0; INSERT INTO t1 VALUES (127,0,1),(188,0,1),(206,0,1),(218,0,1),(292,0,1),(338,0,1),(375,0,1), @@ -139,7 +131,8 @@ DROP TABLE t1,t2,t3; --echo # MDEV-25858: Query results are incorrect when indexes are added --echo # -CREATE TABLE t1 (id int NOT NULL PRIMARY KEY) engine=innodb; +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY) engine=innodb +STATS_PERSISTENT=0; insert into t1 values (1),(2),(3); CREATE TABLE t2 ( diff --git a/mysql-test/main/range_innodb.result b/mysql-test/main/range_innodb.result index 6cd1c133b93..eddfbfd0d62 100644 --- a/mysql-test/main/range_innodb.result +++ b/mysql-test/main/range_innodb.result @@ -1,15 +1,11 @@ # # Range optimizer (and related) tests that need InnoDB. # -drop table if exists t0, t1, t2; # # MDEV-6735: Range checked for each record used with key # create table t0(a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t1(a int); -insert into t1 select A.a + B.a* 10 + C.a * 100 + D.a * 1000 -from t0 A, t0 B, t0 C, t0 D; create table t2 ( a int, b int, @@ -22,12 +18,12 @@ key(b) ) engine=innodb; insert into t2 select -a,a, +seq,seq, repeat('0123456789', 10), repeat('0123456789', 10), repeat('0123456789', 10), repeat('0123456789', 10) -from t1; +from seq_0_to_9999; analyze table t2; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -37,7 +33,7 @@ explain select * from t0 left join t2 on t2.a <t0.a and t2.b between 50 and 250; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t0 ALL NULL NULL NULL NULL 10 1 SIMPLE t2 range a,b b 5 NULL 201 Using where; Using join buffer (flat, BNL join) -drop table t0,t1,t2; +drop table t0,t2; # # MDEV-10466: constructing an invalid SEL_ARG # @@ -89,15 +85,14 @@ drop table t1,t2; # set @optimizer_switch_save= @@optimizer_switch; set optimizer_switch='index_merge_sort_intersection=off'; -create table t0 (a int)engine=innodb; +create table t0(a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 ( a int, b int, c int, key(a),key(b),key(c) )engine=innodb; insert into t1 -select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a -from t0 A, t0 B, t0 C, t0 D where D.a<5; +select a.seq/10, a.seq/10, a.seq from seq_0_to_499 a, seq_0_to_4 b; SET @saved_dbug = @@GLOBAL.debug_dbug; set @@global.debug_dbug="+d,ha_index_init_fail"; explain select * from t1 where a=10 and b=10; diff --git a/mysql-test/main/range_innodb.test b/mysql-test/main/range_innodb.test index b6dea2fbe06..276b9cea08f 100644 --- a/mysql-test/main/range_innodb.test +++ b/mysql-test/main/range_innodb.test @@ -4,12 +4,9 @@ --source include/have_innodb.inc --source include/have_debug.inc +--source include/have_sequence.inc --source include/no_valgrind_without_big.inc ---disable_warnings -drop table if exists t0, t1, t2; ---enable_warnings - --echo # --echo # MDEV-6735: Range checked for each record used with key --echo # @@ -17,10 +14,6 @@ drop table if exists t0, t1, t2; create table t0(a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t1(a int); -insert into t1 select A.a + B.a* 10 + C.a * 100 + D.a * 1000 -from t0 A, t0 B, t0 C, t0 D; - create table t2 ( a int, b int, @@ -34,18 +27,18 @@ create table t2 ( insert into t2 select - a,a, + seq,seq, repeat('0123456789', 10), repeat('0123456789', 10), repeat('0123456789', 10), repeat('0123456789', 10) -from t1; +from seq_0_to_9999; analyze table t2; --echo # The following must not use "Range checked for each record": explain select * from t0 left join t2 on t2.a <t0.a and t2.b between 50 and 250; -drop table t0,t1,t2; +drop table t0,t2; --echo # @@ -98,15 +91,14 @@ drop table t1,t2; set @optimizer_switch_save= @@optimizer_switch; set optimizer_switch='index_merge_sort_intersection=off'; -create table t0 (a int)engine=innodb; +create table t0(a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 ( a int, b int, c int, key(a),key(b),key(c) )engine=innodb; insert into t1 -select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a -from t0 A, t0 B, t0 C, t0 D where D.a<5; +select a.seq/10, a.seq/10, a.seq from seq_0_to_499 a, seq_0_to_4 b; SET @saved_dbug = @@GLOBAL.debug_dbug; set @@global.debug_dbug="+d,ha_index_init_fail"; explain select * from t1 where a=10 and b=10; @@ -122,8 +114,6 @@ set @@optimizer_switch= @optimizer_switch_save; --echo # MDEV-27262: Index intersection with full scan over an index --echo # ---source include/have_sequence.inc - CREATE TABLE t1 ( id int(10) unsigned NOT NULL AUTO_INCREMENT, p char(32) DEFAULT NULL, diff --git a/mysql-test/main/rowid_filter_innodb_debug.result b/mysql-test/main/rowid_filter_innodb_debug.result index 56226fe25ce..5a3fa374bd1 100644 --- a/mysql-test/main/rowid_filter_innodb_debug.result +++ b/mysql-test/main/rowid_filter_innodb_debug.result @@ -2,10 +2,8 @@ set default_storage_engine=innodb; # # MDEV-22761 KILL QUERY during rowid_filter, crashes # -create table t0(a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t2(a int); -insert into t2 select A.a + B.a* 10 from t0 A, t0 B; +insert into t2 select * from seq_0_to_99; CREATE TABLE t3 ( key1 int , key2 int, @@ -19,11 +17,10 @@ engine InnoDB insert into t3 select -A.a, -B.a, +A.seq, +B.seq, 'filler-data-filler-data' -from -t2 A, t2 B; +from seq_0_to_99 A, seq_0_to_99 B; analyze table t2,t3; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -42,7 +39,6 @@ select * from t2, t3 where t3.key1=t2.a and t3.key2 in (2,3); connect con1, localhost, root,,; -connection con1; set debug_sync='now WAIT_FOR at_rowid_filter_check'; kill query $target_id; set debug_sync='now SIGNAL go'; @@ -50,7 +46,7 @@ connection default; disconnect con1; ERROR 70100: Query execution was interrupted set debug_sync='RESET'; -drop table t0,t2,t3; +drop table t2,t3; set default_storage_engine=default; set @save_optimizer_switch= @@optimizer_switch; set @save_use_stat_tables= @@use_stat_tables; @@ -67,7 +63,6 @@ INSERT INTO t1 VALUES (0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4); set debug_sync='handler_rowid_filter_check SIGNAL killme WAIT_FOR go'; SELECT * FROM t1 WHERE a > 0 AND b=0; connect con1, localhost, root,,; -connection con1; set debug_sync='now WAIT_FOR killme'; kill query @id; set debug_sync='now SIGNAL go'; diff --git a/mysql-test/main/rowid_filter_innodb_debug.test b/mysql-test/main/rowid_filter_innodb_debug.test index 31fbd937304..f89a2a82da8 100644 --- a/mysql-test/main/rowid_filter_innodb_debug.test +++ b/mysql-test/main/rowid_filter_innodb_debug.test @@ -31,7 +31,6 @@ set debug_sync='handler_rowid_filter_check SIGNAL killme WAIT_FOR go'; send SELECT * FROM t1 WHERE a > 0 AND b=0; connect (con1, localhost, root,,); -connection con1; let $ignore= `SELECT @id := $ID`; set debug_sync='now WAIT_FOR killme'; kill query @id; diff --git a/mysql-test/main/rowid_filter_myisam_debug.result b/mysql-test/main/rowid_filter_myisam_debug.result index 32a989f50da..75a8fad6947 100644 --- a/mysql-test/main/rowid_filter_myisam_debug.result +++ b/mysql-test/main/rowid_filter_myisam_debug.result @@ -1,10 +1,8 @@ # # MDEV-22761 KILL QUERY during rowid_filter, crashes # -create table t0(a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t2(a int); -insert into t2 select A.a + B.a* 10 from t0 A, t0 B; +insert into t2 select * from seq_0_to_99; CREATE TABLE t3 ( key1 int , key2 int, @@ -18,11 +16,10 @@ engine MyISAM insert into t3 select -A.a, -B.a, +A.seq, +B.seq, 'filler-data-filler-data' -from -t2 A, t2 B; +from seq_0_to_99 A, seq_0_to_99 B; analyze table t2,t3; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -41,7 +38,6 @@ select * from t2, t3 where t3.key1=t2.a and t3.key2 in (2,3); connect con1, localhost, root,,; -connection con1; set debug_sync='now WAIT_FOR at_rowid_filter_check'; kill query $target_id; set debug_sync='now SIGNAL go'; @@ -49,4 +45,4 @@ connection default; disconnect con1; ERROR 70100: Query execution was interrupted set debug_sync='RESET'; -drop table t0,t2,t3; +drop table t2,t3; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index bf1df903947..c0b91a68da7 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -471,6 +471,51 @@ a 1 2 3 +# +# MDEV-29655: ASAN heap-use-after-free in +# Pushdown_derived::Pushdown_derived +# +connection slave; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; +INSERT INTO federated.t1 VALUES +(3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); +connection master; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +use federated; +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 +WHERE id=2) dt2) dt; +id name +connection slave; +CREATE TABLE federated.t10 (a INT,b INT); +CREATE TABLE federated.t11 (a INT, b INT); +INSERT INTO federated.t10 VALUES (1,1),(2,2); +INSERT INTO federated.t11 VALUES (1,1),(2,2); +connection master; +CREATE TABLE federated.t10 +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t10'; +CREATE TABLE federated.t11 +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t11'; +use federated; +SELECT * FROM t10 LEFT JOIN +(t11, (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 +WHERE id=2) dt2) dt +) ON t10.a=t11.a; +a b a b id name +1 1 NULL NULL NULL NULL +2 2 NULL NULL NULL NULL set global federated_pushdown=0; connection master; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index 2d6c2bc4197..f827c141f3d 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -267,7 +267,6 @@ INSERT INTO federated.t2 SELECT * FROM (SELECT * FROM federated.t1 LIMIT 70000) dt; SELECT COUNT(DISTINCT a) FROM federated.t2; - --echo # --echo # MDEV-29640 FederatedX does not properly handle pushdown --echo # in case of difference in local and remote table names @@ -314,6 +313,64 @@ CREATE TABLE federated.t3 (a INT) EXPLAIN SELECT * FROM federated.t3; SELECT * FROM federated.t3; +--echo # +--echo # MDEV-29655: ASAN heap-use-after-free in +--echo # Pushdown_derived::Pushdown_derived +--echo # + +connection slave; +DROP TABLE IF EXISTS federated.t1; + +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; + +INSERT INTO federated.t1 VALUES + (3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); + +connection master; +DROP TABLE IF EXISTS federated.t1; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +use federated; +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 + WHERE id=2) dt2) dt; + +connection slave; +CREATE TABLE federated.t10 (a INT,b INT); +CREATE TABLE federated.t11 (a INT, b INT); +INSERT INTO federated.t10 VALUES (1,1),(2,2); +INSERT INTO federated.t11 VALUES (1,1),(2,2); + +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t10 +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t10'; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t11 +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t11'; + +use federated; +SELECT * FROM t10 LEFT JOIN + (t11, (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 + WHERE id=2) dt2) dt + ) ON t10.a=t11.a; + set global federated_pushdown=0; source include/federated_cleanup.inc; diff --git a/mysql-test/suite/innodb/r/innodb-fkcheck.result b/mysql-test/suite/innodb/r/innodb-fkcheck.result index 2c2be83a3ff..f86ba50597f 100644 --- a/mysql-test/suite/innodb/r/innodb-fkcheck.result +++ b/mysql-test/suite/innodb/r/innodb-fkcheck.result @@ -33,11 +33,19 @@ b bigint unsigned NOT NULL, d1 date NOT NULL, PRIMARY KEY (b,d1) ) ENGINE=InnoDB; +DROP TABLE b; +set foreign_key_checks = 1; +CREATE TABLE b ( +b bigint unsigned NOT NULL, +d1 date NOT NULL, +PRIMARY KEY (b,d1) +) ENGINE=InnoDB; ERROR HY000: Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message Error 1005 Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint for `b` +set foreign_key_checks = 0; DROP TABLE IF EXISTS d; Warnings: Note 1051 Unknown table 'bug_fk.d' diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index edbdcd2b28e..47e5f0f5c94 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2531,9 +2531,19 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; create table t1(a char(10) primary key, b varchar(20)) engine = innodb; -ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") set foreign_key_checks=1; +insert into t2 values (1,1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`)) +set foreign_key_checks=0; +drop table t1; +set foreign_key_checks=1; +insert into t2 values (1,1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`)) +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") drop table t2; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +drop table t1; set foreign_key_checks=0; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; diff --git a/mysql-test/suite/innodb/r/insert_into_empty.result b/mysql-test/suite/innodb/r/insert_into_empty.result index 55828ae0a4f..3267eefdc28 100644 --- a/mysql-test/suite/innodb/r/insert_into_empty.result +++ b/mysql-test/suite/innodb/r/insert_into_empty.result @@ -193,6 +193,7 @@ SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1"; n_rows 4096 DROP TABLE t1; +# End of 10.6 tests # # MDEV-26947 UNIQUE column checks fail in InnoDB resulting # in table corruption @@ -367,3 +368,4 @@ Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= @format; +# End of 10.7 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index 843f33fddd1..f0fedcc7673 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -34,13 +34,15 @@ ROLLBACK; InnoDB 0 transactions not purged INSERT INTO t2 VALUES (16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); +BEGIN; +UPDATE t1 SET c2=c2+1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -UPDATE t1 SET c2=c2+1; +COMMIT; # Kill the server disconnect ddl; # restart @@ -61,6 +63,8 @@ DELETE FROM t2; ROLLBACK; InnoDB 0 transactions not purged INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; ALTER TABLE t2 DROP COLUMN c3; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; @@ -68,7 +72,7 @@ ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; # Kill the server disconnect ddl; # restart @@ -138,6 +142,8 @@ InnoDB 0 transactions not purged # # MDEV-24323 Crash on recovery after kill during instant ADD COLUMN # +BEGIN; +INSERT INTO t1 VALUES(0,0); connect ddl, localhost, root; CREATE TABLE t3(id INT PRIMARY KEY, c2 INT, v2 INT AS(c2) VIRTUAL, UNIQUE(v2)) ENGINE=InnoDB; @@ -147,7 +153,7 @@ ALTER TABLE t3 ADD COLUMN c3 TEXT NOT NULL DEFAULT 'sic transit gloria mundi'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -INSERT INTO t1 VALUES(0,0); +COMMIT; # Kill the server disconnect ddl; # restart @@ -183,13 +189,15 @@ DROP TABLE t2,t3; # CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; # Kill the server disconnect ddl; # restart diff --git a/mysql-test/suite/innodb/r/truncate_foreign.result b/mysql-test/suite/innodb/r/truncate_foreign.result index 3154674aabf..e587baa5288 100644 --- a/mysql-test/suite/innodb/r/truncate_foreign.result +++ b/mysql-test/suite/innodb/r/truncate_foreign.result @@ -80,9 +80,19 @@ SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); LOCK TABLES t1 WRITE; +SET FOREIGN_KEY_CHECKS=1; TRUNCATE t1; ERROR HY000: Cannot add foreign key constraint for `t1` INSERT INTO t1 VALUES (2,2); +ERROR HY000: Table 't1' was not locked with LOCK TABLES +SELECT * FROM t1; +pk a +1 1 +UNLOCK TABLES; +INSERT INTO t1 VALUES (2,2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +SET FOREIGN_KEY_CHECKS=0; +INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; pk a 1 1 diff --git a/mysql-test/suite/innodb/t/innodb-fkcheck.test b/mysql-test/suite/innodb/t/innodb-fkcheck.test index 4657edc4d65..5ff3533fce1 100644 --- a/mysql-test/suite/innodb/t/innodb-fkcheck.test +++ b/mysql-test/suite/innodb/t/innodb-fkcheck.test @@ -46,7 +46,15 @@ show create table c; # # Note that column b has different type in parent table # ---error 1005 +CREATE TABLE b ( + b bigint unsigned NOT NULL, + d1 date NOT NULL, + PRIMARY KEY (b,d1) +) ENGINE=InnoDB; +DROP TABLE b; + +set foreign_key_checks = 1; +--error ER_CANT_CREATE_TABLE CREATE TABLE b ( b bigint unsigned NOT NULL, d1 date NOT NULL, @@ -54,6 +62,7 @@ CREATE TABLE b ( ) ENGINE=InnoDB; show warnings; +set foreign_key_checks = 0; DROP TABLE IF EXISTS d; @@ -64,7 +73,7 @@ CREATE TABLE d ( CONSTRAINT bd_fk FOREIGN KEY (b) REFERENCES b (b) ) ENGINE=InnoDB; -show warnings; +show warnings; set foreign_key_checks = 1; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 3a8c12dfbbd..3b3b2770df7 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1598,12 +1598,22 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +set foreign_key_checks=1; +--error ER_NO_REFERENCED_ROW_2 +insert into t2 values (1,1); +set foreign_key_checks=0; +drop table t1; +set foreign_key_checks=1; +--error ER_NO_REFERENCED_ROW_2 +insert into t2 values (1,1); # Embedded server doesn't chdir to data directory --replace_result $MYSQLTEST_VARDIR . master-data/ '' --error ER_CANT_CREATE_TABLE create table t1(a char(10) primary key, b varchar(20)) engine = innodb; -set foreign_key_checks=1; drop table t2; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +drop table t1; # test that FKs between different charsets are not accepted in CREATE even # when f_k_c is 0 diff --git a/mysql-test/suite/innodb/t/insert_into_empty.test b/mysql-test/suite/innodb/t/insert_into_empty.test index df04a207476..590f76dca9e 100644 --- a/mysql-test/suite/innodb/t/insert_into_empty.test +++ b/mysql-test/suite/innodb/t/insert_into_empty.test @@ -208,6 +208,8 @@ source include/wait_condition.inc; SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1"; DROP TABLE t1; +--echo # End of 10.6 tests + --echo # --echo # MDEV-26947 UNIQUE column checks fail in InnoDB resulting --echo # in table corruption @@ -375,3 +377,5 @@ INSERT IGNORE INTO t1 VALUES CHECK TABLE t1; DROP TABLE t1; SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= @format; + +--echo # End of 10.7 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index 4d211ece106..0bd983a2b4c 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -47,6 +47,9 @@ ROLLBACK; INSERT INTO t2 VALUES (16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); +BEGIN; +UPDATE t1 SET c2=c2+1; + connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send @@ -55,7 +58,7 @@ ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -UPDATE t1 SET c2=c2+1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -73,6 +76,8 @@ ROLLBACK; --source include/wait_all_purged.inc INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +BEGIN; +DELETE FROM t1; connect ddl, localhost, root; ALTER TABLE t2 DROP COLUMN c3; @@ -83,7 +88,7 @@ ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -177,6 +182,9 @@ DELETE FROM t2; --echo # --echo # MDEV-24323 Crash on recovery after kill during instant ADD COLUMN --echo # +BEGIN; +INSERT INTO t1 VALUES(0,0); + connect ddl, localhost, root; CREATE TABLE t3(id INT PRIMARY KEY, c2 INT, v2 INT AS(c2) VIRTUAL, UNIQUE(v2)) ENGINE=InnoDB; @@ -189,7 +197,7 @@ ALTER TABLE t3 ADD COLUMN c3 TEXT NOT NULL DEFAULT 'sic transit gloria mundi'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -INSERT INTO t1 VALUES(0,0); +COMMIT; --source include/kill_mysqld.inc disconnect ddl; @@ -207,6 +215,9 @@ DROP TABLE t2,t3; CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6); +BEGIN; +DELETE FROM t1; + connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send @@ -215,7 +226,7 @@ ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; -DELETE FROM t1; +COMMIT; --source include/kill_mysqld.inc disconnect ddl; diff --git a/mysql-test/suite/innodb/t/truncate_foreign.test b/mysql-test/suite/innodb/t/truncate_foreign.test index e40029e18be..abbe1b3df87 100644 --- a/mysql-test/suite/innodb/t/truncate_foreign.test +++ b/mysql-test/suite/innodb/t/truncate_foreign.test @@ -92,8 +92,19 @@ SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); LOCK TABLES t1 WRITE; +SET FOREIGN_KEY_CHECKS=1; --error ER_CANNOT_ADD_FOREIGN TRUNCATE t1; +# Whether TRUNCATE succeeds or fails, it will reload FOREIGN KEY constraints. +# As a result, ha_innobase::referenced_by_foreign_key() will retun TRUE +# (for the self-referential key), and the statement will fail. +--error ER_TABLE_NOT_LOCKED +INSERT INTO t1 VALUES (2,2); +SELECT * FROM t1; +UNLOCK TABLES; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t1 VALUES (2,2); +SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result index 18f715b9d95..11df7d89f0b 100644 --- a/mysql-test/suite/innodb_fts/r/misc_debug.result +++ b/mysql-test/suite/innodb_fts/r/misc_debug.result @@ -62,7 +62,6 @@ SET @saved_debug_dbug= @@debug_dbug; CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB; SET debug_dbug='+d,ib_create_table_fail_too_many_trx'; TRUNCATE t1; -ERROR HY000: Got error -1 "Internal error < 0 (Not system error)" from storage engine InnoDB SET debug_dbug=@saved_debug_dbug; DROP TABLE t1; # End of 10.3 tests diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test index c086348b631..9246d27a704 100644 --- a/mysql-test/suite/innodb_fts/t/misc_debug.test +++ b/mysql-test/suite/innodb_fts/t/misc_debug.test @@ -91,7 +91,6 @@ SET @saved_debug_dbug= @@debug_dbug; CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB; SET debug_dbug='+d,ib_create_table_fail_too_many_trx'; ---error ER_GET_ERRNO TRUNCATE t1; SET debug_dbug=@saved_debug_dbug; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result index ac4a9c7b1c4..5365e7d0f8c 100644 --- a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result @@ -795,4 +795,14 @@ ENGINE=InnoDB; INSERT INTO t VALUES (REPEAT('MariaDB Corporation Ab ',351),POINT(0,0)); ALTER TABLE t FORCE; DROP TABLE t; +# +# MDEV-29856 heap-use-after-poison in row_merge_spatial_rows() +# with PRIMARY KEY on column prefix +# +CREATE TABLE t (id INT, f TEXT, s POINT NOT NULL, +PRIMARY KEY(id,f(1)), SPATIAL(s)) ENGINE=InnoDB; +INSERT INTO t VALUES +(1,REPEAT('x',8192),@p:=ST_GeomFromText('POINT(0 0)')),(2,'',@p); +ALTER TABLE t FORCE; +DROP TABLE t; # End of 10.3 tests diff --git a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test index 88e10d07b99..6f30b38b6d4 100644 --- a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test @@ -791,4 +791,16 @@ ALTER TABLE t FORCE; # Cleanup DROP TABLE t; +--echo # +--echo # MDEV-29856 heap-use-after-poison in row_merge_spatial_rows() +--echo # with PRIMARY KEY on column prefix +--echo # + +CREATE TABLE t (id INT, f TEXT, s POINT NOT NULL, + PRIMARY KEY(id,f(1)), SPATIAL(s)) ENGINE=InnoDB; +INSERT INTO t VALUES +(1,REPEAT('x',8192),@p:=ST_GeomFromText('POINT(0 0)')),(2,'',@p); +ALTER TABLE t FORCE; +DROP TABLE t; + --echo # End of 10.3 tests diff --git a/mysql-test/suite/innodb_zip/disabled.def b/mysql-test/suite/innodb_zip/disabled.def deleted file mode 100644 index 8b137891791..00000000000 --- a/mysql-test/suite/innodb_zip/disabled.def +++ /dev/null @@ -1 +0,0 @@ - diff --git a/mysql-test/suite/mariabackup/full_backup.opt b/mysql-test/suite/mariabackup/full_backup.opt new file mode 100644 index 00000000000..7928cd812d0 --- /dev/null +++ b/mysql-test/suite/mariabackup/full_backup.opt @@ -0,0 +1 @@ +--innodb_undo_tablespaces=2 diff --git a/mysql-test/suite/mariabackup/full_backup.result b/mysql-test/suite/mariabackup/full_backup.result index e2d5cf185d5..e69d00f86f6 100644 --- a/mysql-test/suite/mariabackup/full_backup.result +++ b/mysql-test/suite/mariabackup/full_backup.result @@ -12,3 +12,18 @@ SELECT * FROM t; i 1 DROP TABLE t; +# +# MDEV-27121 mariabackup incompatible with disabled dedicated +# undo log tablespaces +# +call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); +# restart: --innodb_undo_tablespaces=0 +# xtrabackup backup +# xtrabackup prepare +# shutdown server +# remove datadir +# xtrabackup move back +# restart: --innodb_undo_tablespaces=0 +# Display undo log files from target directory +undo001 +undo002 diff --git a/mysql-test/suite/mariabackup/full_backup.test b/mysql-test/suite/mariabackup/full_backup.test index 66bed34cf3d..a0243527438 100644 --- a/mysql-test/suite/mariabackup/full_backup.test +++ b/mysql-test/suite/mariabackup/full_backup.test @@ -29,3 +29,27 @@ SELECT * FROM t; DROP TABLE t; rmdir $targetdir; +--echo # +--echo # MDEV-27121 mariabackup incompatible with disabled dedicated +--echo # undo log tablespaces +--echo # +call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); + +let $restart_parameters=--innodb_undo_tablespaces=0; +--source include/restart_mysqld.inc + +echo # xtrabackup backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log + +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log + +--echo # Display undo log files from target directory +list_files $targetdir undo*; + +rmdir $targetdir; diff --git a/mysql-test/suite/mariabackup/mdev-14447.combinations b/mysql-test/suite/mariabackup/mdev-14447.combinations new file mode 100644 index 00000000000..79e5f7836ed --- /dev/null +++ b/mysql-test/suite/mariabackup/mdev-14447.combinations @@ -0,0 +1,5 @@ +[crc32] +--innodb-checksum-algorithm=crc32 + +[full_crc32] +--innodb-checksum-algorithm=full_crc32 diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 444a47bb7c5..2d4385f4684 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -202,7 +202,7 @@ int start_addr2line_fork(const char *binary_path) close(out[0]); close(out[1]); execlp("addr2line", "addr2line", "-C", "-f", "-e", binary_path, NULL); - exit(1); + _exit(1); } close(in[0]); @@ -319,12 +319,20 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) /* Save result for future comparisons. */ strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); +#ifdef _AIX + /* + info.dli_fbase is a char on AIX and casting it doesn't fool gcc. + leave backtracing broken on AIX until a real solution can be found. + */ + addr_offset= NULL; +#else /* Check if we should use info.dli_fbase as an offset or not for the base program. This is depending on if the compilation is done with PIE or not. */ - addr_offset= (void*) info.dli_fbase; + addr_offset= info.dli_fbase; +#endif #ifndef __PIE__ if (strcmp(info.dli_fname, my_progname) == 0 && addr_resolve((void*) my_addr_resolve, loc) == 0 && diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 6bba553a549..24054aa4151 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -23,7 +23,7 @@ #ifndef MAIN -#if defined(_AIX) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(__sun) || defined(_WIN32) +#if defined(_AIX) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__sun) || defined(_WIN32) static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) { uint i, res= 1; @@ -35,8 +35,14 @@ static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) } #endif -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ +#include <netinet/in.h> +#include <net/if_arp.h> +#include <netinet/if_ether.h> +#else #include <net/ethernet.h> +#endif #include <sys/sysctl.h> #include <net/route.h> #include <net/if.h> diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc index f48b95cbf76..70cc04bf9c7 100644 --- a/sql/derived_handler.cc +++ b/sql/derived_handler.cc @@ -44,11 +44,6 @@ Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h) } -Pushdown_derived::~Pushdown_derived() -{ - delete handler; -} - int Pushdown_derived::execute() { diff --git a/sql/field.h b/sql/field.h index 059163da82d..196dd6fcaae 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1766,12 +1766,6 @@ public: Used by the ALTER TABLE */ virtual bool is_equal(const Column_definition &new_field) const= 0; - // Used as double dispatch pattern: calls virtual method of handler - virtual bool - can_be_converted_by_engine(const Column_definition &new_type) const - { - return false; - } /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, int *err); @@ -4058,11 +4052,6 @@ public: void sql_type(String &str) const override; void sql_rpl_type(String*) const override; bool is_equal(const Column_definition &new_field) const override; - bool can_be_converted_by_engine(const Column_definition &new_type) const - override - { - return table->file->can_convert_string(this, new_type); - } uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; @@ -4217,11 +4206,6 @@ public: uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit) override; bool is_equal(const Column_definition &new_field) const override; - bool can_be_converted_by_engine(const Column_definition &new_type) const - override - { - return table->file->can_convert_varstring(this, new_type); - } void hash(ulong *nr, ulong *nr2) override; uint length_size() const override { return length_bytes; } void print_key_value(String *out, uint32 length) override; @@ -4660,11 +4644,6 @@ public: uint32 char_length() const override; uint32 character_octet_length() const override; bool is_equal(const Column_definition &new_field) const override; - bool can_be_converted_by_engine(const Column_definition &new_type) const - override - { - return table->file->can_convert_blob(this, new_type); - } void print_key_value(String *out, uint32 length) override; Binlog_type_info binlog_type_info() const override; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a8eebe54868..34cbf8f018a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -12125,35 +12125,12 @@ int ha_partition::info_push(uint info_type, void *info) bool -ha_partition::can_convert_string(const Field_string* field, - const Column_definition& new_type) const +ha_partition::can_convert_nocopy(const Field &field, + const Column_definition &new_type) const { for (uint index= 0; index < m_tot_parts; index++) { - if (!m_file[index]->can_convert_string(field, new_type)) - return false; - } - return true; -} - -bool -ha_partition::can_convert_varstring(const Field_varstring* field, - const Column_definition& new_type) const{ - for (uint index= 0; index < m_tot_parts; index++) - { - if (!m_file[index]->can_convert_varstring(field, new_type)) - return false; - } - return true; -} - -bool -ha_partition::can_convert_blob(const Field_blob* field, - const Column_definition& new_type) const -{ - for (uint index= 0; index < m_tot_parts; index++) - { - if (!m_file[index]->can_convert_blob(field, new_type)) + if (!m_file[index]->can_convert_nocopy(field, new_type)) return false; } return true; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4a4b899708e..437280d6d5d 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1629,16 +1629,8 @@ public: friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2); friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2); - bool can_convert_string( - const Field_string* field, - const Column_definition& new_field) const override; - bool can_convert_varstring( - const Field_varstring* field, - const Column_definition& new_field) const override; - - bool can_convert_blob( - const Field_blob* field, - const Column_definition& new_field) const override; + bool can_convert_nocopy(const Field &field, + const Column_definition &new_field) const override; }; #endif /* HA_PARTITION_INCLUDED */ diff --git a/sql/handler.cc b/sql/handler.cc index 1eddc4f352e..d3de74a8451 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7317,8 +7317,13 @@ int handler::check_duplicate_long_entries_update(const uchar *new_rec) { int error; field= keypart->field; - /* Compare fields if they are different then check for duplicates */ - if (field->cmp_binary_offset(reclength)) + /* + Compare fields if they are different then check for duplicates + cmp_binary_offset cannot differentiate between null and empty string + So also check for that too + */ + if((field->is_null(0) != field->is_null(reclength)) || + field->cmp_binary_offset(reclength)) { if((error= check_duplicate_long_entry_key(new_rec, i))) return error; diff --git a/sql/handler.h b/sql/handler.h index ed24f160385..ad18ad8b9e4 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -5097,18 +5097,8 @@ public: These functions check for such possibility. Implementation could be based on Field_xxx::is_equal() */ - virtual bool can_convert_string(const Field_string *field, - const Column_definition &new_type) const - { - return false; - } - virtual bool can_convert_varstring(const Field_varstring *field, - const Column_definition &new_type) const - { - return false; - } - virtual bool can_convert_blob(const Field_blob *field, - const Column_definition &new_type) const + virtual bool can_convert_nocopy(const Field &, + const Column_definition &) const { return false; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8e209516861..04b1f65715b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4120,8 +4120,8 @@ static int init_common_variables() files= my_set_max_open_files(max_open_files); SYSVAR_AUTOSIZE_IF_CHANGED(open_files_limit, files, ulong); - if (files < wanted_files && global_system_variables.log_warnings) - sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files); + if (files < max_open_files && global_system_variables.log_warnings) + sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, max_open_files); /* If we required too much tc_instances than we reduce */ SYSVAR_AUTOSIZE_IF_CHANGED(tc_instances, diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 579ea34b8e4..6f0857239dd 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1016,11 +1016,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) /* Create an object for execution of the query specifying the table */ if (!(derived->pushdown_derived= new (thd->mem_root) Pushdown_derived(derived, derived->dt_handler))) - { - delete derived->dt_handler; - derived->dt_handler= NULL; DBUG_RETURN(TRUE); - } } lex->current_select= first_select; @@ -1245,7 +1241,6 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) /* Execute the query that specifies the derived table by a foreign engine */ res= derived->pushdown_derived->execute(); unit->executed= true; - delete derived->pushdown_derived; DBUG_RETURN(res); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 419fa4fb1fe..6e914a1529e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -67,6 +67,7 @@ #include "select_handler.h" #include "my_json_writer.h" #include "opt_trace.h" +#include "derived_handler.h" #include "create_tmp_table.h" /* @@ -14578,6 +14579,7 @@ void JOIN::cleanup(bool full) } } } + free_pushdown_handlers(*join_list); } /* Restore ref array to original state */ if (current_ref_ptrs != items0) @@ -14588,6 +14590,32 @@ void JOIN::cleanup(bool full) DBUG_VOID_RETURN; } +/** + Clean up all derived pushdown handlers in this join. + + @detail + Note that dt_handler is picked at the prepare stage (as opposed + to optimization stage where one could expect this). + Because of that, we have to do cleanups in this function that is called + from JOIN::cleanup() and not in JOIN_TAB::cleanup. + */ +void JOIN::free_pushdown_handlers(List<TABLE_LIST>& join_list) +{ + List_iterator<TABLE_LIST> li(join_list); + TABLE_LIST *table_ref; + while ((table_ref= li++)) + { + if (table_ref->nested_join) + free_pushdown_handlers(table_ref->nested_join->join_list); + if (table_ref->pushdown_derived) + { + delete table_ref->pushdown_derived; + table_ref->pushdown_derived= NULL; + } + delete table_ref->dt_handler; + table_ref->dt_handler= NULL; + } +} /** Remove the following expressions from ORDER BY and GROUP BY: @@ -28069,12 +28097,6 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) result, unit, first); } - if (unit->derived && unit->derived->pushdown_derived) - { - delete unit->derived->pushdown_derived; - unit->derived->pushdown_derived= NULL; - } - DBUG_RETURN(res || thd->is_error()); } diff --git a/sql/sql_select.h b/sql/sql_select.h index 5aa775f4a2d..c9e0fa25421 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1791,6 +1791,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<Item> *fields); + void free_pushdown_handlers(List<TABLE_LIST>& join_list); void init_join_cache_and_keyread(); bool transform_in_predicates_into_equalities(THD *thd); bool transform_all_conds_and_on_exprs(THD *thd, @@ -2471,8 +2472,6 @@ public: Pushdown_derived(TABLE_LIST *tbl, derived_handler *h); - ~Pushdown_derived(); - int execute(); }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 833865f17b5..c58b381460b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6535,7 +6535,7 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, bool is_equal= field->is_equal(*new_field); if (!is_equal) { - if (field->can_be_converted_by_engine(*new_field)) + if (field->table->file->can_convert_nocopy(*field, *new_field)) { /* New column type differs from the old one, but storage engine can diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index a2bcd45e0e8..3bc25808bc3 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -2,7 +2,7 @@ #define SQL_TYPE_GEOM_H_INCLUDED /* Copyright (c) 2015 MariaDB Foundation - Copyright (c) 2019 MariaDB + Copyright (c) 2019, 2022, 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 @@ -397,12 +397,6 @@ public: !table->copy_blobs; } bool is_equal(const Column_definition &new_field) const override; - bool can_be_converted_by_engine(const Column_definition &new_type) - const override - { - return false; // Override the Field_blob behavior - } - int store(const char *to, size_t length, CHARSET_INFO *charset) override; int store(double nr) override; int store(longlong nr, bool unsigned_val) override; diff --git a/storage/connect/mysql-test/connect/r/odbc_postgresql.result b/storage/connect/mysql-test/connect/r/odbc_postgresql.result index 6bd8d75a601..9ecb66307e6 100644 --- a/storage/connect/mysql-test/connect/r/odbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/odbc_postgresql.result @@ -319,3 +319,12 @@ SELECT * from pg_in_maria; my space column My value DROP TABLE pg_in_maria; +# +# MDEV-29397 UPDATE with WHERE on part of two-part primary key causes +# info to turn into error. +# +CREATE TABLE t1 (a VARCHAR(6), b VARCHAR(6), PRIMARY KEY(a, b)) ENGINE=CONNECT TABNAME='schema1.t3' CHARSET=utf8 DATA_CHARSET=utf8 TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr'; +UPDATE t1 SET a='10' WHERE a='20'; +Warnings: +Note 1105 schema1.t3: 0 affected rows +DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/t/odbc_postgresql.test b/storage/connect/mysql-test/connect/t/odbc_postgresql.test index ec98453d630..187bec55b38 100644 --- a/storage/connect/mysql-test/connect/t/odbc_postgresql.test +++ b/storage/connect/mysql-test/connect/t/odbc_postgresql.test @@ -223,3 +223,12 @@ DROP TABLE t1; CREATE TABLE pg_in_maria ENGINE=CONNECT TABNAME='schema1.space_in_column_name' CHARSET=utf8 DATA_CHARSET=utf8 TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' quoted=1; SELECT * from pg_in_maria; DROP TABLE pg_in_maria; + +--echo # +--echo # MDEV-29397 UPDATE with WHERE on part of two-part primary key causes +--echo # info to turn into error. +--echo # +CREATE TABLE t1 (a VARCHAR(6), b VARCHAR(6), PRIMARY KEY(a, b)) ENGINE=CONNECT TABNAME='schema1.t3' CHARSET=utf8 DATA_CHARSET=utf8 TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr'; +UPDATE t1 SET a='10' WHERE a='20'; +DROP TABLE t1; + diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 09140712de8..0c5903baa77 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -2583,7 +2583,7 @@ int ODBConn::Rewind(char *sql, ODBCCOL *tocols) int rc, rbuf = -1; if (!m_hstmt) - rbuf = -1; + rbuf = 0; else if (m_Full) rbuf = m_Rows; // No need to "rewind" else if (m_Scrollable) { diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index dcd93539f19..96a9f70e4a3 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -472,7 +472,7 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) my_len= res - buf + 1; my_schema_table= (char *) malloc(my_len); memcpy(my_schema_table, buf, my_len - 1); - my_schema_table[my_len] = 0; + my_schema_table[my_len - 1] = 0; Query->Append(Quote); Query->Append(my_schema_table); Query->Append(Quote); @@ -480,7 +480,7 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) Query->Append("."); // Parse table my_len= strlen(buf) - my_len + 1; - my_schema_table= (char *) malloc(my_len); + my_schema_table= (char *) malloc(my_len + 1); memcpy(my_schema_table, ++res, my_len); my_schema_table[my_len] = 0; Query->Append(Quote); diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 3d5a0c2fb00..223d903c803 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -563,8 +563,9 @@ inline void PageBulk::finish() void PageBulk::commit(bool success) { finish(); - if (success && !dict_index_is_clust(m_index) && page_is_leaf(m_page)) - ibuf_set_bitmap_for_bulk_load(m_block, innobase_fill_factor == 100); + if (success && !m_index->is_clust() && page_is_leaf(m_page)) + ibuf_set_bitmap_for_bulk_load(m_block, &m_mtr, + innobase_fill_factor == 100); m_mtr.commit(); } @@ -634,7 +635,7 @@ PageBulk::getSplitRec() < total_used_size / 2); /* Keep at least one record on left page */ - if (page_rec_is_second(rec, m_page)) { + if (page_rec_is_first(rec, m_page)) { rec = page_rec_get_next(rec); ut_ad(page_rec_is_user_rec(rec)); } diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 4729b4c0408..1d98ce058ed 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -588,7 +588,7 @@ bool buf_page_is_corrupted(bool check_lsn, const byte *read_buf, DBUG_EXECUTE_IF( "page_intermittent_checksum_mismatch", { static int page_counter; - if (page_counter++ == 2) { + if (page_counter++ == 3) { crc32++; } }); @@ -723,7 +723,7 @@ bool buf_page_is_corrupted(bool check_lsn, const byte *read_buf, DBUG_EXECUTE_IF( "page_intermittent_checksum_mismatch", { static int page_counter; - if (page_counter++ == 2) return true; + if (page_counter++ == 3) return true; }); if ((checksum_field1 != crc32 diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 10ad82015ca..34362a6792f 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -685,8 +685,7 @@ dict_acquire_mdl_shared(dict_table_t *table, } else { - ut_ad(dict_sys.frozen()); - ut_ad(!dict_sys.locked()); + ut_ad(dict_sys.frozen_not_locked()); db_len= dict_get_db_name_len(table->name.m_name); } @@ -1003,7 +1002,7 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) latch_ex_wait_start.store(0, std::memory_order_relaxed); ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); return; } @@ -1021,15 +1020,15 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) latch.wr_lock(SRW_LOCK_ARGS(file, line)); ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); } #ifdef UNIV_PFS_RWLOCK ATTRIBUTE_NOINLINE void dict_sys_t::unlock() { - ut_ad(latch_ex); + ut_ad(latch_ex == pthread_self()); ut_ad(!latch_readers); - ut_d(latch_ex= false); + ut_d(latch_ex= 0); latch.wr_unlock(); } @@ -1498,6 +1497,7 @@ dict_table_t::rename_tablespace(span<const char> new_name, bool replace) const err= DB_TABLESPACE_EXISTS; else { + space->x_lock(); err= space->rename(path, true, replace); if (data_dir) { @@ -1505,6 +1505,7 @@ dict_table_t::rename_tablespace(span<const char> new_name, bool replace) const new_name= {name.m_name, strlen(name.m_name)}; RemoteDatafile::delete_link_file(new_name); } + space->x_unlock(); } ut_free(path); @@ -2757,17 +2758,6 @@ dict_index_build_internal_fts( } /*====================== FOREIGN KEY PROCESSING ========================*/ -/*********************************************************************//** -Checks if a table is referenced by foreign keys. -@return TRUE if table is referenced by a foreign key */ -ibool -dict_table_is_referenced_by_foreign_key( -/*====================================*/ - const dict_table_t* table) /*!< in: InnoDB table */ -{ - return(!table->referenced_set.empty()); -} - /**********************************************************************//** Removes a foreign constraint struct from the dictionary cache. */ void diff --git a/storage/innobase/dict/drop.cc b/storage/innobase/dict/drop.cc index edb6add0787..9013841ba5e 100644 --- a/storage/innobase/dict/drop.cc +++ b/storage/innobase/dict/drop.cc @@ -267,8 +267,7 @@ void trx_t::commit(std::vector<pfs_os_file_t> &deleted) if (btr_defragment_active) btr_defragment_remove_table(table); const fil_space_t *space= table->space; - ut_ad(!strstr(table->name.m_name, "/FTS_") || - purge_sys.must_wait_FTS()); + ut_ad(!p.second.is_aux_table() || purge_sys.must_wait_FTS()); dict_sys.remove(table); if (const auto id= space ? space->id : 0) { diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 31c6523c700..efa15251bbe 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1373,6 +1373,13 @@ static dberr_t fts_drop_table(trx_t *trx, const char *table_name, bool rename) return err; } +#ifdef UNIV_DEBUG + for (auto &p : trx->mod_tables) + { + if (p.first == table) + p.second.set_aux_table(); + } +#endif /* UNIV_DEBUG */ return DB_SUCCESS; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dd4f54092b1..acc179f28b5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -54,7 +54,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include <my_bitmap.h> #include <mysql/service_thd_alloc.h> #include <mysql/service_thd_wait.h> -#include "field.h" +#include "sql_type_geom.h" #include "scope.h" #include "srv0srv.h" @@ -11454,6 +11454,8 @@ innobase_fts_load_stopword( trx_t* trx, /*!< in: transaction */ THD* thd) /*!< in: current thread */ { + ut_ad(dict_sys.locked()); + const char *stopword_table= THDVAR(thd, ft_user_stopword_table); if (!stopword_table) { @@ -11463,9 +11465,11 @@ innobase_fts_load_stopword( mysql_mutex_unlock(&LOCK_global_system_variables); } - return !high_level_read_only && - fts_load_stopword(table, trx, stopword_table, - THDVAR(thd, ft_enable_stopword), false); + table->fts->dict_locked= true; + bool success= fts_load_stopword(table, trx, stopword_table, + THDVAR(thd, ft_enable_stopword), false); + table->fts->dict_locked= false; + return success; } /** Parse the table name into normal name and remote path if needed. @@ -12801,15 +12805,18 @@ int create_table_info_t::create_table(bool create_fk) dberr_t err = create_fk ? create_foreign_keys() : DB_SUCCESS; if (err == DB_SUCCESS) { + const dict_err_ignore_t ignore_err = m_trx->check_foreigns + ? DICT_ERR_IGNORE_NONE : DICT_ERR_IGNORE_FK_NOKEY; + /* Check that also referencing constraints are ok */ dict_names_t fk_tables; err = dict_load_foreigns(m_table_name, nullptr, m_trx->id, true, - DICT_ERR_IGNORE_NONE, fk_tables); + ignore_err, fk_tables); while (err == DB_SUCCESS && !fk_tables.empty()) { dict_sys.load_table( {fk_tables.front(), strlen(fk_tables.front())}, - DICT_ERR_IGNORE_NONE); + ignore_err); fk_tables.pop_front(); } } @@ -13090,96 +13097,59 @@ bool create_table_info_t::row_size_is_acceptable( return true; } -/** Update a new table in an InnoDB database. -@return error number */ -int -create_table_info_t::create_table_update_dict() +void create_table_info_t::create_table_update_dict(dict_table_t *table, + THD *thd, + const HA_CREATE_INFO &info, + const TABLE &t) { - dict_table_t* innobase_table; - - DBUG_ENTER("create_table_update_dict"); - - innobase_table = dict_table_open_on_name( - m_table_name, false, DICT_ERR_IGNORE_NONE); - - DBUG_ASSERT(innobase_table != 0); - if (innobase_table->fts != NULL) { - if (innobase_table->fts_doc_id_index == NULL) { - innobase_table->fts_doc_id_index - = dict_table_get_index_on_name( - innobase_table, FTS_DOC_ID_INDEX_NAME); - DBUG_ASSERT(innobase_table->fts_doc_id_index != NULL); - } else { - DBUG_ASSERT(innobase_table->fts_doc_id_index - == dict_table_get_index_on_name( - innobase_table, - FTS_DOC_ID_INDEX_NAME)); - } - } - - DBUG_ASSERT((innobase_table->fts == NULL) - == (innobase_table->fts_doc_id_index == NULL)); - - innobase_copy_frm_flags_from_create_info(innobase_table, m_create_info); + ut_ad(dict_sys.locked()); - dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE); - - /* Load server stopword into FTS cache */ - if (m_flags2 & DICT_TF2_FTS) { - if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) { - innobase_table->release(); - DBUG_RETURN(-1); - } - - dict_sys.lock(SRW_LOCK_CALL); - fts_optimize_add_table(innobase_table); - dict_sys.unlock(); - } + DBUG_ASSERT(table->get_ref_count()); + if (table->fts) + { + if (!table->fts_doc_id_index) + table->fts_doc_id_index= + dict_table_get_index_on_name(table, FTS_DOC_ID_INDEX_NAME); + else + DBUG_ASSERT(table->fts_doc_id_index == + dict_table_get_index_on_name(table, FTS_DOC_ID_INDEX_NAME)); + } - if (const Field* ai = m_form->found_next_number_field) { - ut_ad(ai->stored_in_db()); + DBUG_ASSERT(!table->fts == !table->fts_doc_id_index); - ib_uint64_t autoinc = m_create_info->auto_increment_value; + innobase_copy_frm_flags_from_create_info(table, &info); - if (autoinc == 0) { - autoinc = 1; - } + /* Load server stopword into FTS cache */ + if (table->flags2 & DICT_TF2_FTS && + innobase_fts_load_stopword(table, nullptr, thd)) + fts_optimize_add_table(table); - innobase_table->autoinc_mutex.wr_lock(); - dict_table_autoinc_initialize(innobase_table, autoinc); + if (const Field *ai = t.found_next_number_field) + { + ut_ad(ai->stored_in_db()); + ib_uint64_t autoinc= info.auto_increment_value; + if (autoinc == 0) + autoinc= 1; - if (innobase_table->is_temporary()) { - /* AUTO_INCREMENT is not persistent for - TEMPORARY TABLE. Temporary tables are never - evicted. Keep the counter in memory only. */ - } else { - const unsigned col_no = innodb_col_no(ai); - - innobase_table->persistent_autoinc - = static_cast<uint16_t>( - dict_table_get_nth_col_pos( - innobase_table, col_no, NULL) - + 1) - & dict_index_t::MAX_N_FIELDS; - - /* Persist the "last used" value, which - typically is AUTO_INCREMENT - 1. - In btr_create(), the value 0 was already written. */ - if (--autoinc) { - btr_write_autoinc( - dict_table_get_first_index( - innobase_table), - autoinc); - } - } + table->autoinc_mutex.wr_lock(); + dict_table_autoinc_initialize(table, autoinc); - innobase_table->autoinc_mutex.wr_unlock(); - } + if (!table->is_temporary()) + { + const unsigned col_no= innodb_col_no(ai); + table->persistent_autoinc= static_cast<uint16_t> + (dict_table_get_nth_col_pos(table, col_no, nullptr) + 1) & + dict_index_t::MAX_N_FIELDS; + /* Persist the "last used" value, which typically is AUTO_INCREMENT - 1. + In btr_create(), the value 0 was already written. */ + if (--autoinc) + btr_write_autoinc(dict_table_get_first_index(table), autoinc); + } - innobase_parse_hint_from_comment(m_thd, innobase_table, m_form->s); + table->autoinc_mutex.wr_unlock(); + } - dict_table_close(innobase_table); - DBUG_RETURN(0); + innobase_parse_hint_from_comment(thd, table, t.s); } /** Allocate a new trx. */ @@ -13196,89 +13166,80 @@ create_table_info_t::allocate_trx() @param[in] create_info Create info (including create statement string). @param[in] file_per_table whether to create .ibd file @param[in,out] trx dictionary transaction, or NULL to create new -@return 0 if success else error number. */ -inline int -ha_innobase::create( - const char* name, - TABLE* form, - HA_CREATE_INFO* create_info, - bool file_per_table, - trx_t* trx) +@return error code +@retval 0 on success */ +int +ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info, + bool file_per_table, trx_t *trx= nullptr) { - char norm_name[FN_REFLEN]; /* {database}/{tablename} */ - char remote_path[FN_REFLEN]; /* Absolute path of table */ + char norm_name[FN_REFLEN]; /* {database}/{tablename} */ + char remote_path[FN_REFLEN]; /* Absolute path of table */ - DBUG_ENTER("ha_innobase::create"); + DBUG_ENTER("ha_innobase::create"); + DBUG_ASSERT(form->s == table_share); + DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE || + table_share->table_type == TABLE_TYPE_NORMAL); - DBUG_ASSERT(form->s == table_share); - DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE - || table_share->table_type == TABLE_TYPE_NORMAL); + create_table_info_t info(ha_thd(), form, create_info, norm_name, + remote_path, file_per_table, trx); - create_table_info_t info(ha_thd(), - form, - create_info, - norm_name, - remote_path, - file_per_table, trx); + int error= info.initialize(); + if (!error) + error= info.prepare_create_table(name, !trx); + if (error) + DBUG_RETURN(error); - { - int error = info.initialize(); - if (!error) { - error = info.prepare_create_table(name, !trx); - } - if (error) { - if (trx) { - trx_rollback_for_mysql(trx); - row_mysql_unlock_data_dictionary(trx); - } - DBUG_RETURN(error); - } - } + const bool own_trx= !trx; + if (own_trx) + { + info.allocate_trx(); + trx= info.trx(); + DBUG_ASSERT(trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - const bool own_trx = !trx; - int error = 0; + if (!(info.flags2() & DICT_TF2_TEMPORARY)) + { + trx_start_for_ddl(trx); + if (dberr_t err= lock_sys_tables(trx)) + error= convert_error_code_to_mysql(err, 0, nullptr); + } + row_mysql_lock_data_dictionary(trx); + } - if (own_trx) { - info.allocate_trx(); - trx = info.trx(); - DBUG_ASSERT(trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - } - if (own_trx && !(info.flags2() & DICT_TF2_TEMPORARY)) { - trx_start_for_ddl(trx); - if (dberr_t err = lock_sys_tables(trx)) { - error = convert_error_code_to_mysql(err, 0, nullptr); - } - } - if (own_trx) { - row_mysql_lock_data_dictionary(trx); - } + if (!error) + error= info.create_table(own_trx); - if (!error) { - error = info.create_table(own_trx); - } + if (own_trx || (info.flags2() & DICT_TF2_TEMPORARY)) + { + if (error) + trx_rollback_for_mysql(trx); + else + { + std::vector<pfs_os_file_t> deleted; + trx->commit(deleted); + ut_ad(deleted.empty()); + info.table()->acquire(); + info.create_table_update_dict(info.table(), info.thd(), + *create_info, *form); + } - if (error) { - /* Rollback will drop the being-created table. */ - trx_rollback_for_mysql(trx); - row_mysql_unlock_data_dictionary(trx); - } else { - /* When this is invoked as part of ha_innobase::truncate(), - the old copy of the table will be deleted here. */ - std::vector<pfs_os_file_t> deleted; - trx->commit(deleted); - row_mysql_unlock_data_dictionary(trx); - for (pfs_os_file_t d : deleted) os_file_close(d); - error = info.create_table_update_dict(); - if (!(info.flags2() & DICT_TF2_TEMPORARY)) { - log_write_up_to(trx->commit_lsn, true); - } - } + if (own_trx) + { + row_mysql_unlock_data_dictionary(trx); - if (own_trx) { - trx->free(); - } + if (!error) + { + dict_stats_update(info.table(), DICT_STATS_EMPTY_TABLE); + if (!info.table()->is_temporary()) + log_write_up_to(trx->commit_lsn, true); + info.table()->release(); + } + trx->free(); + } + } + else if (!error && m_prebuilt) + m_prebuilt->table= info.table(); - DBUG_RETURN(error); + DBUG_RETURN(error); } /** Create a new table to an InnoDB database. @@ -13286,13 +13247,10 @@ ha_innobase::create( @param[in] form Table format; columns and index information. @param[in] create_info Create info (including create statement string). @return 0 if success else error number. */ -int -ha_innobase::create( - const char* name, - TABLE* form, - HA_CREATE_INFO* create_info) +int ha_innobase::create(const char *name, TABLE *form, + HA_CREATE_INFO *create_info) { - return create(name, form, create_info, srv_file_per_table); + return create(name, form, create_info, srv_file_per_table); } /*****************************************************************//** @@ -13821,229 +13779,247 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, @retval 0 on success */ int ha_innobase::truncate() { - DBUG_ENTER("ha_innobase::truncate"); + DBUG_ENTER("ha_innobase::truncate"); - update_thd(); + update_thd(); - if (is_read_only()) { - DBUG_RETURN(HA_ERR_TABLE_READONLY); - } + if (is_read_only()) + DBUG_RETURN(HA_ERR_TABLE_READONLY); - HA_CREATE_INFO info; - dict_table_t* ib_table = m_prebuilt->table; - info.init(); - update_create_info_from_table(&info, table); - switch (dict_tf_get_rec_format(ib_table->flags)) { - case REC_FORMAT_REDUNDANT: - info.row_type = ROW_TYPE_REDUNDANT; - break; - case REC_FORMAT_COMPACT: - info.row_type = ROW_TYPE_COMPACT; - break; - case REC_FORMAT_COMPRESSED: - info.row_type = ROW_TYPE_COMPRESSED; - break; - case REC_FORMAT_DYNAMIC: - info.row_type = ROW_TYPE_DYNAMIC; - break; - } + HA_CREATE_INFO info; + dict_table_t *ib_table= m_prebuilt->table; + info.init(); + update_create_info_from_table(&info, table); + switch (dict_tf_get_rec_format(ib_table->flags)) { + case REC_FORMAT_REDUNDANT: + info.row_type= ROW_TYPE_REDUNDANT; + break; + case REC_FORMAT_COMPACT: + info.row_type= ROW_TYPE_COMPACT; + break; + case REC_FORMAT_COMPRESSED: + info.row_type= ROW_TYPE_COMPRESSED; + break; + case REC_FORMAT_DYNAMIC: + info.row_type= ROW_TYPE_DYNAMIC; + break; + } - const auto stored_lock = m_prebuilt->stored_select_lock_type; - trx_t* trx = innobase_trx_allocate(m_user_thd); - trx_start_for_ddl(trx); + const auto stored_lock= m_prebuilt->stored_select_lock_type; + trx_t *trx= innobase_trx_allocate(m_user_thd); + trx_start_for_ddl(trx); - if (ib_table->is_temporary()) { - info.options|= HA_LEX_CREATE_TMP_TABLE; - btr_drop_temporary_table(*ib_table); - m_prebuilt->table = nullptr; - row_prebuilt_free(m_prebuilt); - m_prebuilt = nullptr; - my_free(m_upd_buf); - m_upd_buf = nullptr; - m_upd_buf_size = 0; + if (ib_table->is_temporary()) + { + info.options|= HA_LEX_CREATE_TMP_TABLE; + btr_drop_temporary_table(*ib_table); + m_prebuilt->table= nullptr; + row_prebuilt_free(m_prebuilt); + m_prebuilt= nullptr; + my_free(m_upd_buf); + m_upd_buf= nullptr; + m_upd_buf_size= 0; - row_mysql_lock_data_dictionary(trx); - ib_table->release(); - dict_sys.remove(ib_table, false, true); + row_mysql_lock_data_dictionary(trx); + ib_table->release(); + dict_sys.remove(ib_table, false, true); + int err= create(ib_table->name.m_name, table, &info, true, trx); + row_mysql_unlock_data_dictionary(trx); - int err = create(ib_table->name.m_name, table, &info, true, - trx); - ut_ad(!err); - if (!err) { - err = open(ib_table->name.m_name, 0, 0); - m_prebuilt->stored_select_lock_type = stored_lock; - } + ut_ad(!err); + if (!err) + { + err= open(ib_table->name.m_name, 0, 0); + m_prebuilt->table->release(); + m_prebuilt->stored_select_lock_type= stored_lock; + } - trx->free(); + trx->free(); #ifdef BTR_CUR_HASH_ADAPT - if (UT_LIST_GET_LEN(ib_table->freed_indexes)) { - ib_table->vc_templ = nullptr; - ib_table->id = 0; - DBUG_RETURN(err); - } + if (UT_LIST_GET_LEN(ib_table->freed_indexes)) + { + ib_table->vc_templ= nullptr; + ib_table->id= 0; + } + else #endif /* BTR_CUR_HASH_ADAPT */ + dict_mem_table_free(ib_table); - dict_mem_table_free(ib_table); - DBUG_RETURN(err); - } + DBUG_RETURN(err); + } - mem_heap_t* heap = mem_heap_create(1000); + mem_heap_t *heap= mem_heap_create(1000); - dict_get_and_save_data_dir_path(ib_table); - info.data_file_name = ib_table->data_dir_path; - const char* temp_name = dict_mem_create_temporary_tablename( - heap, ib_table->name.m_name, ib_table->id); - const char* name = mem_heap_strdup(heap, ib_table->name.m_name); + dict_get_and_save_data_dir_path(ib_table); + info.data_file_name= ib_table->data_dir_path; + const char *temp_name= + dict_mem_create_temporary_tablename(heap, + ib_table->name.m_name, ib_table->id); + const char *name= mem_heap_strdup(heap, ib_table->name.m_name); - dict_table_t *table_stats = nullptr, *index_stats = nullptr; - MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; + dict_table_t *table_stats = nullptr, *index_stats = nullptr; + MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; - dberr_t error = DB_SUCCESS; + dberr_t error= DB_SUCCESS; - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : ib_table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + dict_sys.freeze(SRW_LOCK_CALL); + for (const dict_foreign_t *f : ib_table->referenced_set) + if (dict_table_t *child= f->foreign_table) + if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) + break; + dict_sys.unfreeze(); - if (error == DB_SUCCESS) { - error = lock_table_for_trx(ib_table, trx, LOCK_X); - } + if (error == DB_SUCCESS) + error= lock_table_for_trx(ib_table, trx, LOCK_X); - const bool fts = error == DB_SUCCESS - && ib_table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS); + const bool fts= error == DB_SUCCESS && + ib_table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS); - if (fts) { - fts_optimize_remove_table(ib_table); - purge_sys.stop_FTS(*ib_table); - error = fts_lock_tables(trx, *ib_table); - } + if (fts) + { + fts_optimize_remove_table(ib_table); + purge_sys.stop_FTS(*ib_table); + error= fts_lock_tables(trx, *ib_table); + } - /* Wait for purge threads to stop using the table. */ - for (uint n = 15; ib_table->get_ref_count() > 1; ) { - if (!--n) { - error = DB_LOCK_WAIT_TIMEOUT; - break; - } + /* Wait for purge threads to stop using the table. */ + for (uint n = 15; ib_table->get_ref_count() > 1; ) + { + if (!--n) + { + error= DB_LOCK_WAIT_TIMEOUT; + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } + if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) && + !ib_table->is_stats_table()) + { + table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, + DICT_ERR_IGNORE_NONE); + if (table_stats) + { + dict_sys.freeze(SRW_LOCK_CALL); + table_stats= dict_acquire_mdl_shared<false>(table_stats, m_user_thd, + &mdl_table); + dict_sys.unfreeze(); + } + index_stats= dict_table_open_on_name(INDEX_STATS_NAME, false, + DICT_ERR_IGNORE_NONE); + if (index_stats) + { + dict_sys.freeze(SRW_LOCK_CALL); + index_stats= dict_acquire_mdl_shared<false>(index_stats, m_user_thd, + &mdl_index); + dict_sys.unfreeze(); + } - if (error == DB_SUCCESS && dict_stats_is_persistent_enabled(ib_table) - && !ib_table->is_stats_table()) { - table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (table_stats) { - dict_sys.freeze(SRW_LOCK_CALL); - table_stats = dict_acquire_mdl_shared<false>( - table_stats, m_user_thd, &mdl_table); - dict_sys.unfreeze(); - } - index_stats = dict_table_open_on_name(INDEX_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (index_stats) { - dict_sys.freeze(SRW_LOCK_CALL); - index_stats = dict_acquire_mdl_shared<false>( - index_stats, m_user_thd, &mdl_index); - dict_sys.unfreeze(); - } + if (table_stats && index_stats && + !strcmp(table_stats->name.m_name, TABLE_STATS_NAME) && + !strcmp(index_stats->name.m_name, INDEX_STATS_NAME) && + !(error= lock_table_for_trx(table_stats, trx, LOCK_X))) + error= lock_table_for_trx(index_stats, trx, LOCK_X); + } - if (table_stats && index_stats - && !strcmp(table_stats->name.m_name, TABLE_STATS_NAME) - && !strcmp(index_stats->name.m_name, INDEX_STATS_NAME) && - !(error = lock_table_for_trx(table_stats, trx, LOCK_X))) { - error = lock_table_for_trx(index_stats, trx, LOCK_X); - } - } + if (error == DB_SUCCESS) + error= lock_sys_tables(trx); - if (error == DB_SUCCESS) { - error = lock_sys_tables(trx); - } + std::vector<pfs_os_file_t> deleted; - row_mysql_lock_data_dictionary(trx); + row_mysql_lock_data_dictionary(trx); - if (error == DB_SUCCESS) { - error = innobase_rename_table(trx, ib_table->name.m_name, - temp_name, false); + if (error == DB_SUCCESS) + { + error= innobase_rename_table(trx, ib_table->name.m_name, temp_name, false); + if (error == DB_SUCCESS) + error= trx->drop_table(*ib_table); + } - if (error == DB_SUCCESS) { - error = trx->drop_table(*ib_table); - } - } + int err = convert_error_code_to_mysql(error, ib_table->flags, m_user_thd); + const auto update_time = ib_table->update_time; - int err = convert_error_code_to_mysql(error, ib_table->flags, - m_user_thd); - if (err) { - trx_rollback_for_mysql(trx); - if (fts) { - fts_optimize_add_table(ib_table); - purge_sys.resume_FTS(); - } - row_mysql_unlock_data_dictionary(trx); - } else { - const auto update_time = ib_table->update_time; - const auto stored_lock = m_prebuilt->stored_select_lock_type; - const auto def_trx_id = ib_table->def_trx_id; - ib_table->release(); - m_prebuilt->table = nullptr; + if (err) + { + trx_rollback_for_mysql(trx); + if (fts) + fts_optimize_add_table(ib_table); + } + else + { + const auto def_trx_id= ib_table->def_trx_id; + ib_table->release(); + m_prebuilt->table= nullptr; - err = create(name, table, &info, - dict_table_is_file_per_table(ib_table), trx); - /* On success, create() durably committed trx. */ - if (fts) { - purge_sys.resume_FTS(); - } + err= create(name, table, &info, dict_table_is_file_per_table(ib_table), + trx); + if (!err) + { + m_prebuilt->table->acquire(); + create_table_info_t::create_table_update_dict(m_prebuilt->table, + m_user_thd, info, *table); + trx->commit(deleted); + } + else + { + trx_rollback_for_mysql(trx); + m_prebuilt->table= dict_table_open_on_name(name, true, + DICT_ERR_IGNORE_FK_NOKEY); + m_prebuilt->table->def_trx_id= def_trx_id; + } + dict_names_t fk_tables; + dict_load_foreigns(m_prebuilt->table->name.m_name, nullptr, 1, true, + DICT_ERR_IGNORE_FK_NOKEY, fk_tables); + for (const char *f : fk_tables) + dict_sys.load_table({f, strlen(f)}); + } - if (err) { -reload: - m_prebuilt->table = dict_table_open_on_name( - name, false, DICT_ERR_IGNORE_NONE); - m_prebuilt->table->def_trx_id = def_trx_id; - } else { - row_prebuilt_t* prebuilt = m_prebuilt; - uchar* upd_buf = m_upd_buf; - ulint upd_buf_size = m_upd_buf_size; - /* Mimic ha_innobase::close(). */ - m_prebuilt = nullptr; - m_upd_buf = nullptr; - m_upd_buf_size = 0; + if (fts) + purge_sys.resume_FTS(); - err = open(name, 0, 0); + row_mysql_unlock_data_dictionary(trx); + for (pfs_os_file_t d : deleted) os_file_close(d); - if (!err) { - m_prebuilt->stored_select_lock_type - = stored_lock; - m_prebuilt->table->update_time = update_time; - row_prebuilt_free(prebuilt); - my_free(upd_buf); - } else { - /* Revert to the old table. */ - m_prebuilt = prebuilt; - m_upd_buf = upd_buf; - m_upd_buf_size = upd_buf_size; - goto reload; - } - } - } + if (!err) + { + dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE); + log_write_up_to(trx->commit_lsn, true); + row_prebuilt_t *prebuilt= m_prebuilt; + uchar *upd_buf= m_upd_buf; + ulint upd_buf_size= m_upd_buf_size; + /* Mimic ha_innobase::close(). */ + m_prebuilt= nullptr; + m_upd_buf= nullptr; + m_upd_buf_size= 0; + + err= open(name, 0, 0); + if (!err) + { + m_prebuilt->stored_select_lock_type= stored_lock; + m_prebuilt->table->update_time= update_time; + row_prebuilt_free(prebuilt); + my_free(upd_buf); + } + else + { + /* Revert to the old table. */ + m_prebuilt= prebuilt; + m_upd_buf= upd_buf; + m_upd_buf_size= upd_buf_size; + } + } - trx->free(); + trx->free(); - mem_heap_free(heap); + mem_heap_free(heap); - if (table_stats) { - dict_table_close(table_stats, false, m_user_thd, mdl_table); - } - if (index_stats) { - dict_table_close(index_stats, false, m_user_thd, mdl_index); - } + if (table_stats) + dict_table_close(table_stats, false, m_user_thd, mdl_table); + if (index_stats) + dict_table_close(index_stats, false, m_user_thd, mdl_index); - DBUG_RETURN(err); + DBUG_RETURN(err); } /*********************************************************************//** @@ -15637,30 +15613,12 @@ delete is then allowed internally to resolve a duplicate key conflict in REPLACE, not an update. @return > 0 if referenced by a FOREIGN KEY */ -uint -ha_innobase::referenced_by_foreign_key(void) -/*========================================*/ -{ - if (dict_table_is_referenced_by_foreign_key(m_prebuilt->table)) { - - return(1); - } - - return(0); -} - -/*******************************************************************//** -Frees the foreign key create info for a table stored in InnoDB, if it is -non-NULL. */ - -void -ha_innobase::free_foreign_key_create_info( -/*======================================*/ - char* str) /*!< in, own: create info string to free */ +uint ha_innobase::referenced_by_foreign_key() { - if (str != NULL) { - my_free(str); - } + dict_sys.freeze(SRW_LOCK_CALL); + const bool empty= m_prebuilt->table->referenced_set.empty(); + dict_sys.unfreeze(); + return !empty; } /*******************************************************************//** @@ -20639,6 +20597,26 @@ bool ha_innobase::can_convert_blob(const Field_blob *field, return true; } + +bool ha_innobase::can_convert_nocopy(const Field &field, + const Column_definition &new_type) const +{ + if (const Field_string *tf= dynamic_cast<const Field_string *>(&field)) + return can_convert_string(tf, new_type); + + if (const Field_varstring *tf= dynamic_cast<const Field_varstring *>(&field)) + return can_convert_varstring(tf, new_type); + + if (dynamic_cast<const Field_geom *>(&field)) + return false; + + if (const Field_blob *tf= dynamic_cast<const Field_blob *>(&field)) + return can_convert_blob(tf, new_type); + + return false; +} + + Compare_keys ha_innobase::compare_key_parts( const Field &old_field, const Column_definition &new_field, const KEY_PART_INFO &old_part, const KEY_PART_INFO &new_part) const @@ -20649,7 +20627,7 @@ Compare_keys ha_innobase::compare_key_parts( if (!is_equal) { - if (!old_field.can_be_converted_by_engine(new_field)) + if (!old_field.table->file->can_convert_nocopy(old_field, new_field)) return Compare_keys::NotEqual; if (!Charset(old_cs).eq_collation_specific_names(new_cs)) diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 01acde3d8e6..1f42bf180a8 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -190,12 +190,12 @@ public: void update_create_info(HA_CREATE_INFO* create_info) override; - inline int create( + int create( const char* name, TABLE* form, HA_CREATE_INFO* create_info, bool file_per_table, - trx_t* trx = NULL); + trx_t* trx); int create( const char* name, @@ -225,7 +225,7 @@ public: uint referenced_by_foreign_key() override; - void free_foreign_key_create_info(char* str) override; + void free_foreign_key_create_info(char* str) override { my_free(str); } uint lock_count(void) const override; @@ -422,15 +422,9 @@ public: @retval false if pushed (always) */ bool rowid_filter_push(Rowid_filter *rowid_filter) override; - bool - can_convert_string(const Field_string* field, - const Column_definition& new_field) const override; - bool can_convert_varstring( - const Field_varstring* field, - const Column_definition& new_field) const override; - bool - can_convert_blob(const Field_blob* field, - const Column_definition& new_field) const override; + bool can_convert_nocopy(const Field &field, + const Column_definition& new_field) const + override; /** @return whether innodb_strict_mode is active */ static bool is_innodb_strict_mode(THD* thd); @@ -445,6 +439,16 @@ public: const KEY_PART_INFO& new_part) const override; protected: + bool + can_convert_string(const Field_string* field, + const Column_definition& new_field) const; + bool can_convert_varstring( + const Field_varstring* field, + const Column_definition& new_field) const; + bool + can_convert_blob(const Field_blob* field, + const Column_definition& new_field) const; + dberr_t innobase_get_autoinc(ulonglong* value); dberr_t innobase_lock_autoinc(); ulonglong innobase_peek_autoinc(); @@ -639,8 +643,9 @@ public: @param create_fk whether to add FOREIGN KEY constraints */ int create_table(bool create_fk = true); - /** Update the internal data dictionary. */ - int create_table_update_dict(); + static void create_table_update_dict(dict_table_t* table, THD* thd, + const HA_CREATE_INFO& info, + const TABLE& t); /** Validates the create options. Checks that the options KEY_BLOCK_SIZE, ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE @@ -700,12 +705,13 @@ public: trx_t* trx() const { return(m_trx); } - /** Return table name. */ - const char* table_name() const - { return(m_table_name); } + /** @return table name */ + const char* table_name() const { return(m_table_name); } + + /** @return the created table */ + dict_table_t *table() const { return m_table; } - THD* thd() const - { return(m_thd); } + THD* thd() const { return(m_thd); } private: /** Parses the table name into normal name and either temp path or diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 544c1eeadc1..1f46f66a1b7 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7286,13 +7286,10 @@ error_handling_drop_uncached: goto error_handling; } - ctx->new_table->fts->dict_locked = true; - error = innobase_fts_load_stopword( ctx->new_table, ctx->trx, ctx->prebuilt->trx->mysql_thd) ? DB_SUCCESS : DB_ERROR; - ctx->new_table->fts->dict_locked = false; if (error != DB_SUCCESS) { goto error_handling; @@ -9882,7 +9879,7 @@ innobase_update_foreign_cache( err = dict_load_foreigns(user_table->name.m_name, ctx->col_names, 1, true, - DICT_ERR_IGNORE_NONE, + DICT_ERR_IGNORE_FK_NOKEY, fk_tables); if (err == DB_CANNOT_ADD_CONSTRAINT) { diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 82b8968876f..bb2f1b6beda 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -6491,7 +6491,9 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*) { space.reacquire(); mysql_mutex_unlock(&fil_system.mutex); + space.s_lock(); err= i_s_sys_tablespaces_fill(thd, space, tables->table); + space.s_unlock(); mysql_mutex_lock(&fil_system.mutex); space.release(); if (err) @@ -6719,8 +6721,10 @@ i_s_tablespaces_encryption_fill_table( && !space.is_stopping()) { space.reacquire(); mysql_mutex_unlock(&fil_system.mutex); + space.s_lock(); err = i_s_dict_fill_tablespaces_encryption( thd, &space, tables->table); + space.s_unlock(); mysql_mutex_lock(&fil_system.mutex); space.release(); if (err) { diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 0a6e951dbaa..37b00a8ff21 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -2464,6 +2464,7 @@ ibuf_merge_space( ut_ad(space < SRV_SPACE_ID_UPPER_BOUND); + log_free_check(); ibuf_mtr_start(&mtr); /* Position the cursor on the first matching record. */ @@ -2566,6 +2567,7 @@ ulint ibuf_merge_all() ulint n_pages = srv_io_capacity; for (ulint sum_pages = 0; sum_pages < n_pages; ) { + log_free_check(); ulint n_pag2; ulint n_bytes = ibuf_merge(&n_pag2); @@ -4461,7 +4463,7 @@ reset_bit: } /** Delete all change buffer entries for a tablespace, -in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery. +in DISCARD TABLESPACE, IMPORT TABLESPACE, or read-ahead. @param[in] space missing or to-be-discarded tablespace */ void ibuf_delete_for_discarded_space(uint32_t space) { @@ -4483,6 +4485,7 @@ void ibuf_delete_for_discarded_space(uint32_t space) memset(dops, 0, sizeof(dops)); loop: + log_free_check(); ibuf_mtr_start(&mtr); /* Position pcur in the insert buffer at the first entry for the @@ -4622,9 +4625,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) } mtr_start(&mtr); - - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - ibuf_enter(&mtr); buf_block_t* bitmap_page = ibuf_bitmap_get_map_page( @@ -4712,29 +4712,18 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) return(DB_SUCCESS); } -/** Updates free bits and buffered bits for bulk loaded page. -@param[in] block index page -@param[in] reset flag if reset free val */ -void -ibuf_set_bitmap_for_bulk_load( - buf_block_t* block, - bool reset) +void ibuf_set_bitmap_for_bulk_load(buf_block_t *block, mtr_t *mtr, bool reset) { - mtr_t mtr; - ut_a(page_is_leaf(block->page.frame)); - mtr.start(); - fil_space_t *space= mtr.set_named_space_id(block->page.id().space()); if (buf_block_t *bitmap_page= - ibuf_bitmap_get_map_page(block->page.id(), space->zip_size(), &mtr)) + ibuf_bitmap_get_map_page(block->page.id(), block->zip_size(), mtr)) { ulint free_val= reset ? 0 : ibuf_index_page_calc_free(block); /* FIXME: update the bitmap byte only once! */ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE> - (bitmap_page, block->page.id(), block->physical_size(), free_val, &mtr); + (bitmap_page, block->page.id(), block->physical_size(), free_val, mtr); ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED> - (bitmap_page, block->page.id(), block->physical_size(), false, &mtr); + (bitmap_page, block->page.id(), block->physical_size(), false, mtr); } - mtr.commit(); } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index a76fec31416..f70e50f5d48 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -421,14 +421,6 @@ dict_foreign_add_to_cache( dict_err_ignore_t ignore_err) /*!< in: error to be ignored */ MY_ATTRIBUTE((nonnull(1), warn_unused_result)); -/*********************************************************************//** -Checks if a table is referenced by foreign keys. -@return TRUE if table is referenced by a foreign key */ -ibool -dict_table_is_referenced_by_foreign_key( -/*====================================*/ - const dict_table_t* table) /*!< in: InnoDB table */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /**********************************************************************//** Replace the index passed in with another equivalent index in the foreign key lists of the table. @@ -1326,7 +1318,7 @@ class dict_sys_t alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; #ifdef UNIV_DEBUG /** whether latch is being held in exclusive mode (by any thread) */ - bool latch_ex; + Atomic_relaxed<pthread_t> latch_ex; /** number of S-latch holders */ Atomic_counter<uint32_t> latch_readers; #endif @@ -1500,11 +1492,12 @@ public: /** @return whether any thread (not necessarily the current thread) is holding the latch; that is, this check may return false positives */ - bool frozen() const { return latch_readers || locked(); } + bool frozen() const { return latch_readers || latch_ex; } /** @return whether any thread (not necessarily the current thread) - is holding the exclusive latch; that is, this check may return false - positives */ - bool locked() const { return latch_ex; } + is holding a shared latch */ + bool frozen_not_locked() const { return latch_readers; } + /** @return whether the current thread holds the exclusive latch */ + bool locked() const { return latch_ex == pthread_self(); } #endif private: /** Acquire the exclusive latch */ @@ -1523,7 +1516,7 @@ public: { ut_ad(!latch_readers); ut_ad(!latch_ex); - ut_d(latch_ex= true); + ut_d(latch_ex= pthread_self()); } else lock_wait(SRW_LOCK_ARGS(file, line)); @@ -1540,9 +1533,9 @@ public: /** Unlock the data dictionary cache. */ void unlock() { - ut_ad(latch_ex); + ut_ad(latch_ex == pthread_self()); ut_ad(!latch_readers); - ut_d(latch_ex= false); + ut_d(latch_ex= 0); latch.wr_unlock(); } /** Acquire a shared lock on the dictionary cache. */ diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index a94823b4a86..f7d33d5b43b 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -100,7 +100,7 @@ dict_load_foreigns( which must be loaded subsequently to load all the foreign key constraints. */ - MY_ATTRIBUTE((nonnull(1), warn_unused_result)); + MY_ATTRIBUTE((nonnull(1))); /********************************************************************//** This function opens a system table, and return the first record. diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 23d5258cfbc..e6f72b05087 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -264,7 +264,6 @@ ibuf_page_low( MY_ATTRIBUTE((warn_unused_result)); #ifdef UNIV_DEBUG - /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @param[in] page_id tablespace/page identifier @@ -274,7 +273,7 @@ Must not be called when recv_no_ibuf_operations==true. # define ibuf_page(page_id, zip_size, mtr) \ ibuf_page_low(page_id, zip_size, true, mtr) -#else /* UVIV_DEBUG */ +#else /* UNIV_DEBUG */ /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @@ -285,7 +284,7 @@ Must not be called when recv_no_ibuf_operations==true. # define ibuf_page(page_id, zip_size, mtr) \ ibuf_page_low(page_id, zip_size, mtr) -#endif /* UVIV_DEBUG */ +#endif /* UNIV_DEBUG */ /***********************************************************************//** Frees excess pages from the ibuf free list. This function is called when an OS thread calls fsp services to allocate a new file segment, or a new page to a @@ -334,7 +333,7 @@ dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block, ulint zip_size); /** Delete all change buffer entries for a tablespace, -in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery. +in DISCARD TABLESPACE, IMPORT TABLESPACE, or read-ahead. @param[in] space missing or to-be-discarded tablespace */ void ibuf_delete_for_discarded_space(uint32_t space); @@ -385,13 +384,11 @@ ibuf_close(void); dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Updates free bits and buffered bits for bulk loaded page. -@param[in] block index page -@param]in] reset flag if reset free val */ -void -ibuf_set_bitmap_for_bulk_load( - buf_block_t* block, - bool reset); +/** Update free bits and buffered bits for bulk loaded page. +@param block secondary index leaf page +@param mtr mini-transaction +@param reset whether the page is full */ +void ibuf_set_bitmap_for_bulk_load(buf_block_t *block, mtr_t *mtr, bool reset); #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index b0e2eb98d01..0ad42474f84 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -795,17 +795,6 @@ page_rec_is_first( MY_ATTRIBUTE((warn_unused_result)); /************************************************************//** -true if the record is the second user record on a page. -@return true if the second user record */ -UNIV_INLINE -bool -page_rec_is_second( -/*===============*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ - MY_ATTRIBUTE((warn_unused_result)); - -/************************************************************//** true if the record is the last user record on a page. @return true if the last user record */ UNIV_INLINE @@ -817,17 +806,6 @@ page_rec_is_last( MY_ATTRIBUTE((warn_unused_result)); /************************************************************//** -true if the record is the second last user record on a page. -@return true if the second last user record */ -UNIV_INLINE -bool -page_rec_is_second_last( -/*====================*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ - MY_ATTRIBUTE((warn_unused_result)); - -/************************************************************//** Returns the maximum combined size of records which can be inserted on top of record heap. @return maximum combined size for inserted records */ diff --git a/storage/innobase/include/page0page.inl b/storage/innobase/include/page0page.inl index 61c1b96ff79..6c0167edcf9 100644 --- a/storage/innobase/include/page0page.inl +++ b/storage/innobase/include/page0page.inl @@ -193,22 +193,6 @@ page_rec_is_first( } /************************************************************//** -true if the record is the second user record on a page. -@return true if the second user record */ -UNIV_INLINE -bool -page_rec_is_second( -/*===============*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 1); - if (const rec_t *first= page_rec_get_next_const(page_get_infimum_rec(page))) - return page_rec_get_next_const(first) == rec; - return false; -} - -/************************************************************//** true if the record is the last user record on a page. @return true if the last user record */ UNIV_INLINE @@ -224,24 +208,6 @@ page_rec_is_last( } /************************************************************//** -true if the record is the second last user record on a page. -@return true if the second last user record */ -UNIV_INLINE -bool -page_rec_is_second_last( -/*====================*/ - const rec_t* rec, /*!< in: record */ - const page_t* page) /*!< in: page */ -{ - ut_ad(page_get_n_recs(page) > 1); - ut_ad(!page_rec_is_last(rec, page)); - - if (const rec_t *next= page_rec_get_next_const(rec)) - return page_rec_is_supremum(page_rec_get_next_const(next)); - return false; -} - -/************************************************************//** Returns the middle record of the records on the page. If there is an even number of records in the list, returns the first record of the upper half-list. diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 7933e9bc883..de3f617f76d 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -430,6 +430,10 @@ class trx_mod_table_time_t /** First modification of a system versioned column (NONE= no versioning, BULK= the table was dropped) */ undo_no_t first_versioned= NONE; +#ifdef UNIV_DEBUG + /** Whether the modified table is a FTS auxiliary table */ + bool fts_aux_table= false; +#endif /* UNIV_DEBUG */ /** Buffer to store insert opertion */ row_merge_bulk_t *bulk_store= nullptr; @@ -496,6 +500,12 @@ public: return false; } +#ifdef UNIV_DEBUG + void set_aux_table() { fts_aux_table= true; } + + bool is_aux_table() const { return fts_aux_table; } +#endif /* UNIV_DEBUG */ + /** @return the first undo record that modified the table */ undo_no_t get_first() const { diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 448021d840a..db4035157b0 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3934,8 +3934,7 @@ void lock_release(trx_t *trx) #ifdef UNIV_DEBUG std::set<table_id_t> to_evict; if (innodb_evict_tables_on_commit_debug && - !trx->is_recovered && !trx->dict_operation && - !trx->dict_operation_lock_mode) + !trx->is_recovered && !dict_sys.locked()) for (const auto& p : trx->mod_tables) if (!p.first->is_temporary()) to_evict.emplace(p.first->id); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index da0f0668d1d..183500e19c3 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1828,8 +1828,8 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() log_sys.set_flushed_lsn(lsn); const lsn_t source_offset= log_sys.log.calc_lsn_offset_old(lsn); - static const char NO_UPGRADE_RECOVERY_MSG[]= - "Upgrade after a crash is not supported." + static constexpr char NO_UPGRADE_RECOVERY_MSG[]= + "InnoDB: Upgrade after a crash is not supported." " This redo log was created before MariaDB 10.2.2"; recv_sys.read(source_offset & ~511, {buf, 512}); @@ -1837,8 +1837,7 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf) && !log_crypt_101_read_block(buf, lsn)) { - sql_print_error("InnoDB: %s, and it appears corrupted.", - NO_UPGRADE_RECOVERY_MSG); + sql_print_error("%s, and it appears corrupted.", NO_UPGRADE_RECOVERY_MSG); return DB_CORRUPTION; } @@ -1858,7 +1857,10 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() sql_print_error("InnoDB: Cannot decrypt log for upgrading." " The encrypted log was created before MariaDB 10.2.2."); else - sql_print_error("InnoDB: %s.", NO_UPGRADE_RECOVERY_MSG); + sql_print_error("%s. You must start up and shut down" + " MariaDB 10.1 or MySQL 5.6 or earlier" + " on the data directory.", + NO_UPGRADE_RECOVERY_MSG); return DB_ERROR; } @@ -1964,7 +1966,7 @@ recv_find_max_checkpoint(ulint* max_field) if (log_sys.log.format != log_t::FORMAT_3_23 && !recv_check_log_header_checksum(buf)) { sql_print_error("InnoDB: Invalid redo log header checksum."); - return(DB_CORRUPTION); + return DB_CORRUPTION; } char creator[LOG_HEADER_CREATOR_END - LOG_HEADER_CREATOR + 1]; @@ -1988,7 +1990,7 @@ recv_find_max_checkpoint(ulint* max_field) default: sql_print_error("InnoDB: Unsupported redo log format." " The redo log was created with %s.", creator); - return(DB_ERROR); + return DB_ERROR; } for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; @@ -2044,7 +2046,7 @@ recv_find_max_checkpoint(ulint* max_field) " (corrupted redo log)." " You can try --innodb-force-recovery=6" " as a last resort."); - return(DB_ERROR); + return DB_ERROR; } switch (log_sys.log.format) { @@ -2053,12 +2055,15 @@ recv_find_max_checkpoint(ulint* max_field) break; default: if (dberr_t err = recv_log_recover_10_4()) { - sql_print_error("InnoDB: Upgrade after a crash" - " is not supported." + sql_print_error("InnoDB: Upgrade after a crash " + "is not supported." " The redo log was created with %s%s.", creator, - (err == DB_ERROR - ? "" : ", and it appears corrupted")); + err == DB_ERROR + ? ". You must start up and shut down" + " MariaDB 10.4 or earlier" + " on the data directory" + : ", and it appears corrupted"); return err; } } diff --git a/storage/innobase/plugin_exports b/storage/innobase/plugin_exports deleted file mode 100644 index 235ae3d5e72..00000000000 --- a/storage/innobase/plugin_exports +++ /dev/null @@ -1,14 +0,0 @@ -{ - global: - _maria_plugin_interface_version_; - _maria_sizeof_struct_st_plugin_; - _maria_plugin_declarations_; - my_snprintf_service; - thd_alloc_service; - thd_autoinc_service; - thd_error_context_service; - thd_kill_statement_service; - thd_wait_service; - local: - *; -}; diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index 80c34af2790..c5fe7c04a17 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -260,17 +260,10 @@ que_graph_free_recursive( ind_node_t* cre_ind; purge_node_t* purge; - DBUG_ENTER("que_graph_free_recursive"); - if (node == NULL) { - - DBUG_VOID_RETURN; + return; } - DBUG_PRINT("que_graph_free_recursive", - ("node: %p, type: " ULINTPF, node, - que_node_get_type(node))); - switch (que_node_get_type(node)) { case QUE_NODE_FORK: @@ -410,8 +403,6 @@ que_graph_free_recursive( default: ut_error; } - - DBUG_VOID_RETURN; } /**********************************************************************//** @@ -507,66 +498,6 @@ que_node_get_containing_loop_node( return(node); } -#ifdef DBUG_TRACE -/** Gets information of an SQL query graph node. -@return type description */ -static MY_ATTRIBUTE((warn_unused_result, nonnull)) -const char* -que_node_type_string( -/*=================*/ - const que_node_t* node) /*!< in: query graph node */ -{ - switch (que_node_get_type(node)) { - case QUE_NODE_SELECT: - return("SELECT"); - case QUE_NODE_INSERT: - return("INSERT"); - case QUE_NODE_UPDATE: - return("UPDATE"); - case QUE_NODE_WHILE: - return("WHILE"); - case QUE_NODE_ASSIGNMENT: - return("ASSIGNMENT"); - case QUE_NODE_IF: - return("IF"); - case QUE_NODE_FETCH: - return("FETCH"); - case QUE_NODE_OPEN: - return("OPEN"); - case QUE_NODE_PROC: - return("STORED PROCEDURE"); - case QUE_NODE_FUNC: - return("FUNCTION"); - case QUE_NODE_LOCK: - return("LOCK"); - case QUE_NODE_THR: - return("QUERY THREAD"); - case QUE_NODE_COMMIT: - return("COMMIT"); - case QUE_NODE_UNDO: - return("UNDO ROW"); - case QUE_NODE_PURGE: - return("PURGE ROW"); - case QUE_NODE_ROLLBACK: - return("ROLLBACK"); - case QUE_NODE_CREATE_TABLE: - return("CREATE TABLE"); - case QUE_NODE_CREATE_INDEX: - return("CREATE INDEX"); - case QUE_NODE_FOR: - return("FOR LOOP"); - case QUE_NODE_RETURN: - return("RETURN"); - case QUE_NODE_EXIT: - return("EXIT"); - default: - ut_ad(0); - return("UNKNOWN NODE TYPE"); - } -} -#endif /* DBUG_TRACE */ - - /**********************************************************************//** Performs an execution step of an open or close cursor statement node. @param thr query thread */ @@ -614,10 +545,6 @@ que_thr_step( old_thr = thr; - DBUG_PRINT("ib_que", ("Execute %u (%s) at %p", - unsigned(type), que_node_type_string(node), - (const void*) node)); - if (type & QUE_NODE_CONTROL_STAT) { if ((thr->prev_node != que_node_get_parent(node)) && que_node_get_next(thr->prev_node)) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 81882f84c8a..c8e94991500 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -61,57 +61,49 @@ Completed by Sunny Bains and Marko Makela /* Whether to disable file system cache */ char srv_disable_sort_file_cache; -/** Class that caches index row tuples made from a single cluster +/** Class that caches spatial index row tuples made from a single cluster index page scan, and then insert into corresponding index tree */ -class index_tuple_info_t { +class spatial_index_info { public: - /** constructor - @param[in] heap memory heap - @param[in] index index to be created */ - index_tuple_info_t(mem_heap_t* heap, dict_index_t* index) : - m_dtuple_vec(UT_NEW_NOKEY(idx_tuple_vec())), - m_index(index), m_heap(heap) - { ut_ad(index->is_spatial()); } - - /** destructor */ - ~index_tuple_info_t() - { - UT_DELETE(m_dtuple_vec); - } - - /** Get the index object - @return the index object */ - dict_index_t* get_index() UNIV_NOTHROW - { - return(m_index); - } - - /** Caches an index row into index tuple vector - @param[in] row table row - @param[in] ext externally stored column - prefixes, or NULL */ - void add( - const dtuple_t* row, - const row_ext_t* ext) UNIV_NOTHROW - { - dtuple_t* dtuple; - - dtuple = row_build_index_entry(row, ext, m_index, m_heap); - - ut_ad(dtuple); + /** constructor + @param index spatial index to be created */ + spatial_index_info(dict_index_t *index) : index(index) + { + ut_ad(index->is_spatial()); + } - m_dtuple_vec->push_back(dtuple); - } + /** Caches an index row into index tuple vector + @param[in] row table row + @param[in] ext externally stored column prefixes, or NULL */ + void add(const dtuple_t *row, const row_ext_t *ext, mem_heap_t *heap) + { + dtuple_t *dtuple= row_build_index_entry(row, ext, index, heap); + ut_ad(dtuple); + ut_ad(dtuple->n_fields == index->n_fields); + if (ext) + { + /* Replace any references to ext, because ext will be allocated + from row_heap. */ + for (ulint i= 1; i < dtuple->n_fields; i++) + { + dfield_t &dfield= dtuple->fields[i]; + if (dfield.data >= ext->buf && + dfield.data <= &ext->buf[ext->n_ext * ext->max_len]) + dfield_dup(&dfield, heap); + } + } + m_dtuple_vec.push_back(dtuple); + } /** Insert spatial index rows cached in vector into spatial index @param[in] trx_id transaction id - @param[in,out] row_heap memory heap @param[in] pcur cluster index scanning cursor @param[in,out] mtr_started whether scan_mtr is active + @param[in,out] heap temporary memory heap @param[in,out] scan_mtr mini-transaction for pcur @return DB_SUCCESS if successful, else error number */ - dberr_t insert(trx_id_t trx_id, mem_heap_t* row_heap, btr_pcur_t* pcur, - bool& mtr_started, mtr_t* scan_mtr) const + dberr_t insert(trx_id_t trx_id, btr_pcur_t* pcur, + bool& mtr_started, mem_heap_t* heap, mtr_t* scan_mtr) { big_rec_t* big_rec; rec_t* rec; @@ -130,8 +122,8 @@ public: DBUG_EXECUTE_IF("row_merge_instrument_log_check_flush", log_sys.set_check_flush_or_checkpoint();); - for (idx_tuple_vec::iterator it = m_dtuple_vec->begin(); - it != m_dtuple_vec->end(); + for (idx_tuple_vec::iterator it = m_dtuple_vec.begin(); + it != m_dtuple_vec.end(); ++it) { dtuple = *it; ut_ad(dtuple); @@ -151,29 +143,29 @@ public: } mtr.start(); - m_index->set_modified(mtr); + index->set_modified(mtr); - ins_cur.index = m_index; - rtr_init_rtr_info(&rtr_info, false, &ins_cur, m_index, + ins_cur.index = index; + rtr_init_rtr_info(&rtr_info, false, &ins_cur, index, false); rtr_info_update_btr(&ins_cur, &rtr_info); error = btr_cur_search_to_nth_level( - m_index, 0, dtuple, PAGE_CUR_RTREE_INSERT, + index, 0, dtuple, PAGE_CUR_RTREE_INSERT, BTR_MODIFY_LEAF, &ins_cur, &mtr); /* It need to update MBR in parent entry, so change search mode to BTR_MODIFY_TREE */ if (error == DB_SUCCESS && rtr_info.mbr_adj) { - mtr_commit(&mtr); + mtr.commit(); rtr_clean_rtr_info(&rtr_info, true); rtr_init_rtr_info(&rtr_info, false, &ins_cur, - m_index, false); + index, false); rtr_info_update_btr(&ins_cur, &rtr_info); - mtr_start(&mtr); - m_index->set_modified(mtr); + mtr.start(); + index->set_modified(mtr); error = btr_cur_search_to_nth_level( - m_index, 0, dtuple, + index, 0, dtuple, PAGE_CUR_RTREE_INSERT, BTR_MODIFY_TREE, &ins_cur, &mtr); } @@ -181,7 +173,7 @@ public: if (error == DB_SUCCESS) { error = btr_cur_optimistic_insert( flag, &ins_cur, &ins_offsets, - &row_heap, dtuple, &rec, &big_rec, + &heap, dtuple, &rec, &big_rec, 0, NULL, &mtr); } @@ -190,15 +182,15 @@ public: if (error == DB_FAIL) { mtr.commit(); mtr.start(); - m_index->set_modified(mtr); + index->set_modified(mtr); rtr_clean_rtr_info(&rtr_info, true); rtr_init_rtr_info(&rtr_info, false, - &ins_cur, m_index, false); + &ins_cur, index, false); rtr_info_update_btr(&ins_cur, &rtr_info); error = btr_cur_search_to_nth_level( - m_index, 0, dtuple, + index, 0, dtuple, PAGE_CUR_RTREE_INSERT, BTR_MODIFY_TREE, &ins_cur, &mtr); @@ -206,7 +198,7 @@ public: if (error == DB_SUCCESS) { error = btr_cur_pessimistic_insert( flag, &ins_cur, &ins_offsets, - &row_heap, dtuple, &rec, + &heap, dtuple, &rec, &big_rec, 0, NULL, &mtr); } } @@ -232,30 +224,26 @@ public: } } - mtr_commit(&mtr); + mtr.commit(); rtr_clean_rtr_info(&rtr_info, true); } - m_dtuple_vec->clear(); + m_dtuple_vec.clear(); return(error); } private: - /** Cache index rows made from a cluster index scan. Usually - for rows on single cluster index page */ - typedef std::vector<dtuple_t*, ut_allocator<dtuple_t*> > - idx_tuple_vec; + /** Cache index rows made from a cluster index scan. Usually + for rows on single cluster index page */ + typedef std::vector<dtuple_t*, ut_allocator<dtuple_t*> > idx_tuple_vec; - /** vector used to cache index rows made from cluster index scan */ - idx_tuple_vec* const m_dtuple_vec; - - /** the index being built */ - dict_index_t* const m_index; - - /** memory heap for creating index tuples */ - mem_heap_t* const m_heap; + /** vector used to cache index rows made from cluster index scan */ + idx_tuple_vec m_dtuple_vec; +public: + /** the index being built */ + dict_index_t*const index; }; /* Maximum pending doc memory limit in bytes for a fts tokenization thread */ @@ -1749,8 +1737,7 @@ row_mtuple_cmp( @param[in] trx_id transaction id @param[in] sp_tuples cached spatial rows @param[in] num_spatial number of spatial indexes -@param[in,out] heap heap for insert -@param[in,out] sp_heap heap for tuples +@param[in,out] heap temporary memory heap @param[in,out] pcur cluster index cursor @param[in,out] started whether mtr is active @param[in,out] mtr mini-transaction @@ -1759,10 +1746,9 @@ static dberr_t row_merge_spatial_rows( trx_id_t trx_id, - index_tuple_info_t** sp_tuples, + spatial_index_info** sp_tuples, ulint num_spatial, mem_heap_t* heap, - mem_heap_t* sp_heap, btr_pcur_t* pcur, bool& started, mtr_t* mtr) @@ -1771,10 +1757,10 @@ row_merge_spatial_rows( return DB_SUCCESS; for (ulint j= 0; j < num_spatial; j++) - if (dberr_t err= sp_tuples[j]->insert(trx_id, heap, pcur, started, mtr)) + if (dberr_t err= sp_tuples[j]->insert(trx_id, pcur, started, heap, mtr)) return err; - mem_heap_empty(sp_heap); + mem_heap_empty(heap); return DB_SUCCESS; } @@ -1890,8 +1876,7 @@ row_merge_read_clustered_index( doc_id_t max_doc_id = 0; ibool add_doc_id = FALSE; pthread_cond_t* fts_parallel_sort_cond = nullptr; - index_tuple_info_t** sp_tuples = NULL; - mem_heap_t* sp_heap = NULL; + spatial_index_info** sp_tuples = nullptr; ulint num_spatial = 0; BtrBulk* clust_btr_bulk = NULL; bool clust_temp_file = false; @@ -1980,9 +1965,7 @@ row_merge_read_clustered_index( if (num_spatial > 0) { ulint count = 0; - sp_heap = mem_heap_create(512); - - sp_tuples = static_cast<index_tuple_info_t**>( + sp_tuples = static_cast<spatial_index_info**>( ut_malloc_nokey(num_spatial * sizeof(*sp_tuples))); @@ -1990,9 +1973,7 @@ row_merge_read_clustered_index( if (dict_index_is_spatial(index[i])) { sp_tuples[count] = UT_NEW_NOKEY( - index_tuple_info_t( - sp_heap, - index[i])); + spatial_index_info(index[i])); count++; } } @@ -2167,7 +2148,7 @@ corrupted_rec: /* Insert the cached spatial index rows. */ err = row_merge_spatial_rows( trx->id, sp_tuples, num_spatial, - row_heap, sp_heap, &pcur, mtr_started, &mtr); + row_heap, &pcur, mtr_started, &mtr); if (err != DB_SUCCESS) { goto func_exit; @@ -2561,7 +2542,7 @@ write_buffers: continue; } - ut_ad(sp_tuples[s_idx_cnt]->get_index() + ut_ad(sp_tuples[s_idx_cnt]->index == buf->index); /* If the geometry field is invalid, report @@ -2571,7 +2552,7 @@ write_buffers: break; } - sp_tuples[s_idx_cnt]->add(row, ext); + sp_tuples[s_idx_cnt]->add(row, ext, buf->heap); s_idx_cnt++; continue; @@ -2693,7 +2674,7 @@ write_buffers: err = row_merge_spatial_rows( trx->id, sp_tuples, num_spatial, - row_heap, sp_heap, + row_heap, &pcur, mtr_started, &mtr); @@ -3059,10 +3040,6 @@ wait_again: UT_DELETE(sp_tuples[i]); } ut_free(sp_tuples); - - if (sp_heap) { - mem_heap_free(sp_heap); - } } /* Update the next Doc ID we used. Table should be locked, so |