From eb37c17d34c5f9b3ab29e911ec80672b0dacb326 Mon Sep 17 00:00:00 2001 From: "serg@serg.mysql.com" <> Date: Thu, 5 Dec 2002 01:01:38 +0100 Subject: [PATCH 1/7] better fix for read_rows, same for read_one_row --- libmysql/libmysql.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 3c1353e0088..9db1e1c9ab9 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -939,7 +939,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, else { cur->data[field] = to; - if (to+len > end_to) + if (len > end_to - to) { free_rows(result); net->last_errno=CR_UNKNOWN_ERROR; @@ -980,7 +980,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) { uint field; ulong pkt_len,len; - uchar *pos,*prev_pos; + uchar *pos,*prev_pos, *end_pos; if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error) return -1; @@ -988,6 +988,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) return 1; /* End of data */ prev_pos= 0; /* allowed to write at packet[-1] */ pos=mysql->net.read_pos; + end_pos=pos+pkt_len; for (field=0 ; field < fields ; field++) { if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) @@ -997,6 +998,12 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) } else { + if (len > end_pos - pos) + { + mysql->net.last_errno=CR_UNKNOWN_ERROR; + strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + return -1; + } row[field] = (char*) pos; pos+=len; *lengths++=len; From 5c3c4d3721fbc2630e9d70c4a9e35246855eef8a Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 5 Dec 2002 22:03:24 +0200 Subject: [PATCH 2/7] row0mysql.c, dict0dict.c, db0err.h, ha_innobase.cc: Heikki will merge to 4.0: Prevent listing the same column twice in an InnoDB index: that will cause index corruption when that col is UPDATEd --- innobase/dict/dict0dict.c | 21 ++++++++++++++++++++ innobase/include/db0err.h | 2 ++ innobase/row/row0mysql.c | 40 ++++++++++++++++++++++++++++++++------- sql/ha_innobase.cc | 6 +++++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 65f40d345d8..eb9610a6e73 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1033,6 +1033,7 @@ dict_index_add_to_cache( ulint n_ord; ibool success; ulint i; + ulint j; ut_ad(index); ut_ad(mutex_own(&(dict_sys->mutex))); @@ -1063,6 +1064,26 @@ dict_index_add_to_cache( return(FALSE); } + /* Check that the same column does not appear twice in the index. + InnoDB assumes this in its algorithms, e.g., update of an index + entry */ + + for (i = 0; i < dict_index_get_n_fields(index); i++) { + + for (j = 0; j < i; j++) { + if (dict_index_get_nth_field(index, j)->col + == dict_index_get_nth_field(index, i)->col) { + + fprintf(stderr, +"InnoDB: Error: column %s appears twice in index %s of table %s\n" +"InnoDB: This is not allowed in InnoDB.\n" +"InnoDB: UPDATE can cause such an index to become corrupt in InnoDB.\n", + dict_index_get_nth_field(index, i)->col->name, + index->name, table->name); + } + } + } + /* Build the cache internal representation of the index, containing also the added system fields */ diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h index ddfbd5b7862..df74b06dfc0 100644 --- a/innobase/include/db0err.h +++ b/innobase/include/db0err.h @@ -42,6 +42,8 @@ Created 5/24/1996 Heikki Tuuri #define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint to a table failed */ +#define DB_COL_APPEARS_TWICE_IN_INDEX 40 + /* The following are partial failure codes */ #define DB_FAIL 1000 #define DB_OVERFLOW 1001 diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 705ded785fc..325e931b455 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1393,7 +1393,7 @@ int row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ - dict_index_t* index, /* in: index defintion */ + dict_index_t* index, /* in: index definition */ trx_t* trx) /* in: transaction handle */ { ind_node_t* node; @@ -1402,11 +1402,14 @@ row_create_index_for_mysql( ulint namelen; ulint keywordlen; ulint err; + ulint i; + ulint j; + ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx->op_info = "creating index"; + trx->op_info = (char *) "creating index"; trx_start_if_not_started(trx); @@ -1422,6 +1425,29 @@ row_create_index_for_mysql( return(DB_SUCCESS); } + /* Check that the same column does not appear twice in the index. + InnoDB assumes this in its algorithms, e.g., update of an index + entry */ + + for (i = 0; i < dict_index_get_n_fields(index); i++) { + for (j = 0; j < i; j++) { + if (0 == ut_strcmp( + dict_index_get_nth_field(index, j)->name, + dict_index_get_nth_field(index, i)->name)) { + + fprintf(stderr, +"InnoDB: Error: column %s appears twice in index %s\n" +"InnoDB: This is not allowed in InnoDB.\n", + dict_index_get_nth_field(index, i)->name, + index->name); + + err = DB_COL_APPEARS_TWICE_IN_INDEX; + + goto error_handling; + } + } + } + heap = mem_heap_create(512); trx->dict_operation = TRUE; @@ -1434,11 +1460,13 @@ row_create_index_for_mysql( SESS_COMM_EXECUTE, 0)); que_run_threads(thr); - err = trx->error_state; + err = trx->error_state; + que_graph_free((que_t*) que_node_get_parent(thr)); + +error_handling: if (err != DB_SUCCESS) { /* We have special error handling here */ - ut_a(err == DB_OUT_OF_FILE_SPACE); trx->error_state = DB_SUCCESS; @@ -1448,10 +1476,8 @@ row_create_index_for_mysql( trx->error_state = DB_SUCCESS; } - - que_graph_free((que_t*) que_node_get_parent(thr)); - trx->op_info = ""; + trx->op_info = (char *) ""; return((int) err); } diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 2f79f8d6ba9..489c2fafd9b 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -233,10 +233,14 @@ convert_error_code_to_mysql( return(HA_ERR_ROW_IS_REFERENCED); - } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { + } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { return(HA_ERR_CANNOT_ADD_FOREIGN); + } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { + + return(HA_ERR_WRONG_TABLE_DEF); + } else if (error == (int) DB_OUT_OF_FILE_SPACE) { return(HA_ERR_RECORD_FILE_FULL); From fdcb314fc6892bbe10b72a194fb5d462ffeb58ee Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 5 Dec 2002 22:09:51 +0200 Subject: [PATCH 3/7] row0mysql.c: Heikki will merge to 4.0: cleanup --- innobase/row/row0mysql.c | 1 - 1 file changed, 1 deletion(-) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 325e931b455..f0aa413a64c 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1405,7 +1405,6 @@ row_create_index_for_mysql( ulint i; ulint j; - ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); From c5e18e6ad27f9795377edd466e8d4a9658a74375 Mon Sep 17 00:00:00 2001 From: "miguel@hegel.br" <> Date: Tue, 10 Dec 2002 04:17:31 -0400 Subject: [PATCH 4/7] Update Windows binaries prefix according MySQL Pro release package --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6aa41f9f800..0895013c37e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -184,12 +184,12 @@ static char **opt_argv; #ifdef __WIN__ #undef MYSQL_SERVER_SUFFIX #ifdef __NT__ -#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#if defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max-nt" #else #define MYSQL_SERVER_SUFFIX "-nt" #endif /* ...DB */ -#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#elif defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max" #else #define MYSQL_SERVER_SUFFIX "" From 059b0017dc395a430a2103f23278044e9130ecfc Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 10 Dec 2002 14:25:23 +0100 Subject: [PATCH 5/7] - make sure to replace HOSTNAME in mysql.server when packing up the binary distribution (this will still be broken for 3.23.54) - make sure that mysql.server in the binary distribution is executable, too --- scripts/make_binary_distribution.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index bde77713d63..d8d34229b70 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -120,11 +120,11 @@ $CP scripts/* $BASE/bin rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_db $BASE/bin/make_binary_distribution $BASE/bin/setsomevars $BASE/support-files/Makefile* $BASE/support-files/*.sh $BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db -$BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server +$BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server $BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/safe_mysqld mv $BASE/support-files/binary-configure $BASE/configure -chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/configure +chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/support-files/mysql.server $BASE/configure $CP -r sql-bench/* $BASE/sql-bench rm -f $BASE/sql-bench/*.sh $BASE/sql-bench/Makefile* $BASE/lib/*.la From c1b233ec55bc9218d3d53e352090c4054fdce38b Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Wed, 11 Dec 2002 12:44:17 +0200 Subject: [PATCH 6/7] Fixed rare bug in show processlist which could cause core dump if a new thread was connecting. --- sql/sql_show.cc | 12 +++++++----- sql/sql_udf.cc | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 12979f77e56..a6285cfacd0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1025,6 +1025,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) THD *tmp; while ((tmp=it++)) { + struct st_my_thread_var *mysys_var; if ((tmp->net.vio || tmp->system_thread) && (!user || (tmp->user && !strcmp(tmp->user,user)))) { @@ -1034,12 +1035,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->user=thd->strdup(tmp->user ? tmp->user : (tmp->system_thread ? "system user" : "unauthenticated user")); thd_info->host=thd->strdup(tmp->host ? tmp->host : (tmp->ip ? tmp->ip : - (tmp->system_thread ? "none" : "connecting host"))); + (tmp->system_thread ? "none" : + "connecting host"))); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; - if (tmp->mysys_var) - pthread_mutex_lock(&tmp->mysys_var->mutex); + if ((mysys_var= tmp->mysys_var)) + pthread_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0); thd_info->state_info= (char*) (tmp->locked ? "Locked" : tmp->net.reading_or_writing ? @@ -1051,8 +1053,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) tmp->mysys_var && tmp->mysys_var->current_cond ? "Waiting on cond" : NullS); - if (tmp->mysys_var) - pthread_mutex_unlock(&tmp->mysys_var->mutex); + if (mysys_var) + pthread_mutex_unlock(&mysys_var->mutex); #if !defined(DONT_USE_THR_ALARM) && ! defined(SCO) if (pthread_kill(tmp->real_id,0)) diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 5705dccd8d0..82a5e5bc002 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -204,6 +204,8 @@ void udf_init() new_thd->version--; // Force close to free memory close_thread_tables(new_thd); delete new_thd; + /* Remember that we don't have a THD */ + my_pthread_setspecific_ptr(THR_THD, 0); DBUG_VOID_RETURN; } From 53ac261312965b2baf35a8ef66ccdad35af43ea8 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Wed, 11 Dec 2002 12:59:55 +0200 Subject: [PATCH 7/7] Added back -max to server name if we are using InnoDB. --- libmysql/libmysql.c | 4 ++-- sql/mysqld.cc | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 9db1e1c9ab9..755d85dd04a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -939,7 +939,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, else { cur->data[field] = to; - if (len > end_to - to) + if (len > (ulong) (end_to - to)) { free_rows(result); net->last_errno=CR_UNKNOWN_ERROR; @@ -998,7 +998,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) } else { - if (len > end_pos - pos) + if (len > (ulong) (end_pos - pos)) { mysql->net.last_errno=CR_UNKNOWN_ERROR; strmov(mysql->net.last_error,ER(mysql->net.last_errno)); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0895013c37e..17cf8f79646 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -184,17 +184,17 @@ static char **opt_argv; #ifdef __WIN__ #undef MYSQL_SERVER_SUFFIX #ifdef __NT__ -#if defined(HAVE_BERKELEY_DB) +#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max-nt" #else #define MYSQL_SERVER_SUFFIX "-nt" #endif /* ...DB */ -#elif defined(HAVE_BERKELEY_DB) +#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max" #else #define MYSQL_SERVER_SUFFIX "" #endif /* __NT__ */ -#endif +#endif /* __WIN__ */ #ifdef HAVE_BERKELEY_DB SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;