From 556d6d2ebc750fe7ca3df089c5dfcd3d566c96f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jun 2003 14:47:23 +0200 Subject: [PATCH 01/28] - replaced obsolete Macro AM_CONFIG_HEADER with AC_CONFIG_HEADERS - Added missing function name in checking for sem_init in posix4 libs on Solaris --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9b6a174b0fb..d45aecdf494 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! AM_INIT_AUTOMAKE(mysql, 4.0.14) -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS(config.h) PROTOCOL_VERSION=10 DOT_FRM_VERSION=6 @@ -757,7 +757,7 @@ AC_CHECK_LIB(crypt, crypt) AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT)) # For sem_xxx functions on Solaris 2.6 -AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4)) +AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init)) # For compress in zlib MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib) From 800bbfa04e0692a78fd790f6ad5b06c48d200d95 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 16:35:20 +0200 Subject: [PATCH 02/28] Better error reporting in mysql-test-run (don't hide the important message with 'head'). Test fix (this sync_with_master was nonsense). Now all tests pass in 4.0 in autobuild. mysql-test/mysql-test-run.sh: Error reporting (how mysql-test-run filters the messages which mysqltest prints on stderr) is not reliable. It does a 'head the first line only' which in my case caused me to lose some time, because in fact the worrying message was on the second line (logically, the one which caused the die() is at the end of the $TIMEFILE file, not at the beginning). Doing a 'tail' is better but not perfect (depending on the build, one may get "Maximum memory usage" as the last line); it's always good to have all messages and spot the important one oneself. So we print all $TIMEFILE (that's a few lines at most). mysql-test/t/rpl_rotate_logs.test: Dont sync_with_master as the SQL slave thread may be stopped at this moment; just wait_for_slave_to_stop. Doing sync_with_master caused a non-deterministic behaviour, because (note that save_master_pos was called to early) sometimes MASTER_POS_WAIT() started before the SQL thread died (because of unique violation) so returned 0, other times it started after the SQL thread died so returned NULL (which is reported by mysqltest as an error, on stderr). --- mysql-test/mysql-test-run.sh | 4 +++- mysql-test/t/rpl_rotate_logs.test | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 1d25a4d0e3d..55adc3d88fc 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -569,7 +569,9 @@ error () { } error_is () { - $CAT < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)/ \>\> Error at line \1: \2<\ Date: Tue, 17 Jun 2003 23:19:38 +0200 Subject: [PATCH 03/28] Changed change_master() to use ER_MASTER_INFO (better display). mysql-test/r/rpl_rotate_logs.result: result update mysql-test/t/rpl_rotate_logs.test: comments and test update with the error code sql/slave.cc: A DBUG_PRINT sql/sql_repl.cc: Use ER_MASTER_INFO instead of custom message and zero error code (which display badly). --- mysql-test/r/rpl_rotate_logs.result | 2 +- mysql-test/t/rpl_rotate_logs.test | 10 ++++++++-- sql/slave.cc | 1 + sql/sql_repl.cc | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index 741c53fe52b..f49006e8e05 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -5,7 +5,7 @@ Could not initialize master info structure, check permisions on master.info slave start; Could not initialize master info structure, check permisions on master.info change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; -Could not initialize master info +Could not initialize master info structure, check permisions on master.info reset slave; change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; reset master; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 9f7f44d7c28..c4dc5de38da 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -16,14 +16,20 @@ system cat /dev/null > var/slave-data/master.info; system chmod 000 var/slave-data/master.info; connection slave; drop table if exists t1, t2, t3, t4; +# START SLAVE will fail because it can't read the file (mode 000) (system error 13) --error 1201 slave start; system chmod 600 var/slave-data/master.info; +# It will fail again because the file is empty so the slave cannot get valuable +# info about how to connect to the master from it (failure in +# init_strvar_from_file() in init_master_info()). --error 1201 slave start; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT -# Will get error 13 on Unix systems becasue file is not readable -!eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; +# CHANGE MASTER will fail because it first parses master.info before changing it +# (so when master.info is bad, people have to use RESET SLAVE first). +--error 1201 +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; reset slave; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; diff --git a/sql/slave.cc b/sql/slave.cc index dc9ce9715d8..6c29d1a98bc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1644,6 +1644,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi) if (mi->host[0]) { + DBUG_PRINT("info",("host is set: '%s'", mi->host)); String *packet= &thd->packet; packet->length(0); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index a651d8002fd..e3af076da1f 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -828,7 +828,7 @@ int change_master(THD* thd, MASTER_INFO* mi) // TODO: see if needs re-write if (init_master_info(mi, master_info_file, relay_log_info_file, 0)) { - send_error(&thd->net, 0, "Could not initialize master info"); + send_error(&thd->net, ER_MASTER_INFO); unlock_slave_threads(mi); DBUG_RETURN(1); } From 1efc292be6c92316b16eef70b289f6e1ab7f2a33 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 02:18:19 +0300 Subject: [PATCH 04/28] row0vers.c, row0sel.c, row0ins.c: Fix bug: InnoDB could print that it cannot find a clustered index record if an update undo, purge, and a consistent read coincided, in rare cases it might also have returned a wrong row in a query innobase/row/row0ins.c: Fix bug: InnoDB could print that it cannot find a clustered index record if an update undo, purge, and a consistent read coincided, in rare cases it might also have returned a wrong row in a query innobase/row/row0sel.c: Fix bug: InnoDB could print that it cannot find a clustered index record if an update undo, purge, and a consistent read coincided, in rare cases it might also have returned a wrong row in a query innobase/row/row0vers.c: Fix bug: InnoDB could print that it cannot find a clustered index record if an update undo, purge, and a consistent read coincided, in rare cases it might also have returned a wrong row in a query --- innobase/row/row0ins.c | 25 ++++++------ innobase/row/row0sel.c | 89 +++++++++++++++++++++++++++++------------ innobase/row/row0vers.c | 28 +++++-------- 3 files changed, 88 insertions(+), 54 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 23da0b9b93c..d36e5a9761e 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -791,27 +791,28 @@ row_ins_foreign_check_on_constraint( mem_heap_free(tmp_heap); clust_rec = btr_pcur_get_rec(cascade->pcur); - } - if (!page_rec_is_user_rec(clust_rec)) { - fprintf(stderr, + if (btr_pcur_get_low_match(cascade->pcur) + < dict_index_get_n_unique(clust_index)) { + fprintf(stderr, "InnoDB: error in cascade of a foreign key op\n" "InnoDB: index %s table %s\n", index->name, index->table->name); - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, "InnoDB: record %s\n", err_buf); - rec_sprintf(err_buf, 900, clust_rec); - fprintf(stderr, "InnoDB: clustered record %s\n", err_buf); - - fprintf(stderr, + rec_sprintf(err_buf, 900, clust_rec); + fprintf(stderr, "InnoDB: clustered record %s\n", + err_buf); + fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n"); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - err = DB_SUCCESS; + err = DB_SUCCESS; - goto nonstandard_exit_func; + goto nonstandard_exit_func; + } } /* Set an X-lock on the row to delete or update in the child table */ diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 114ebf870b0..afc01247347 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -609,7 +609,25 @@ row_sel_get_clust_rec( clust_rec = btr_pcur_get_rec(&(plan->clust_pcur)); - ut_ad(page_rec_is_user_rec(clust_rec)); + if (btr_pcur_get_low_match(&(plan->clust_pcur)) + < dict_index_get_n_unique(index)) { + + ut_a(rec_get_deleted_flag(rec)); + ut_a(node->read_view); + + /* In a rare case it is possible that no clust rec is found + for a delete-marked secondary index record: if in row0umod.c + in row_undo_mod_remove_clust_low() we have already removed + the clust rec, while purge is still cleaning and removing + secondary index records associated with earlier versions of + the clustered index record. In that case we know that the + clustered index record did not exist in the read view of + trx. */ + + clust_rec = NULL; + + goto func_exit; + } if (!node->read_view) { /* Try to place a lock on the index record */ @@ -672,6 +690,7 @@ row_sel_get_clust_rec( row_sel_fetch_columns(index, clust_rec, UT_LIST_GET_FIRST(plan->columns)); +func_exit: *out_rec = clust_rec; return(DB_SUCCESS); @@ -1253,6 +1272,8 @@ rec_loop: /* PHASE 3: Get previous version in a consistent read */ + cons_read_requires_clust_rec = FALSE; + if (consistent_read) { /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ @@ -2269,7 +2290,10 @@ row_sel_get_clust_rec_for_mysql( /* out: DB_SUCCESS or error code */ row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */ dict_index_t* sec_index,/* in: secondary index where rec resides */ - rec_t* rec, /* in: record in a non-clustered index */ + rec_t* rec, /* in: record in a non-clustered index; if + this is a locking read, then rec is not + allowed to be delete-marked, and that would + not make sense either */ que_thr_t* thr, /* in: query thread */ rec_t** out_rec,/* out: clustered record or an old version of it, NULL if the old version did not exist @@ -2285,7 +2309,7 @@ row_sel_get_clust_rec_for_mysql( ulint err; trx_t* trx; char err_buf[1000]; - + *out_rec = NULL; row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec); @@ -2298,26 +2322,43 @@ row_sel_get_clust_rec_for_mysql( clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); - if (!page_rec_is_user_rec(clust_rec)) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: error clustered record for sec rec not found\n" - "InnoDB: index %s table %s\n", sec_index->name, - sec_index->table->name); + if (btr_pcur_get_low_match(prebuilt->clust_pcur) + < dict_index_get_n_unique(clust_index)) { + + /* In a rare case it is possible that no clust rec is found + for a delete-marked secondary index record: if in row0umod.c + in row_undo_mod_remove_clust_low() we have already removed + the clust rec, while purge is still cleaning and removing + secondary index records associated with earlier versions of + the clustered index record. In that case we know that the + clustered index record did not exist in the read view of + trx. */ - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: sec index record %s\n", err_buf); + if (!rec_get_deleted_flag(rec) + || prebuilt->select_lock_type != LOCK_NONE) { - rec_sprintf(err_buf, 900, clust_rec); - fprintf(stderr, "InnoDB: clust index record %s\n", err_buf); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: error clustered record for sec rec not found\n" + "InnoDB: index %s table %s\n", sec_index->name, + sec_index->table->name); - trx = thr_get_trx(thr); - trx_print(err_buf, trx); + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, + "InnoDB: sec index record %s\n", err_buf); - fprintf(stderr, - "%s\nInnoDB: Make a detailed bug report and send it\n", - err_buf); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + rec_sprintf(err_buf, 900, clust_rec); + fprintf(stderr, + "InnoDB: clust index record %s\n", err_buf); + + trx = thr_get_trx(thr); + trx_print(err_buf, trx); + + fprintf(stderr, + "%s\nInnoDB: Make a detailed bug report and send it\n", + err_buf); + fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + } clust_rec = NULL; @@ -2989,8 +3030,6 @@ rec_loop: /*-------------------------------------------------------------*/ /* PHASE 4: Look for matching records in a loop */ - cons_read_requires_clust_rec = FALSE; - rec = btr_pcur_get_rec(pcur); /* printf("Using index %s cnt %lu ", index->name, cnt); @@ -3145,6 +3184,8 @@ rec_loop: /* We are ready to look at a possible new index entry in the result set: the cursor is now placed on a user record */ + cons_read_requires_clust_rec = FALSE; + if (prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a lock on the index record; note that delete marked records are a special case in a unique search. If there @@ -3170,8 +3211,6 @@ rec_loop: /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - cons_read_requires_clust_rec = FALSE; - if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) { /* Do nothing: we let a non-locking SELECT read the @@ -3215,7 +3254,7 @@ rec_loop: if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) { - /* The record is delete marked: we can skip it if this is + /* The record is delete-marked: we can skip it if this is not a consistent read which might see an earlier version of a non-clustered index record */ @@ -3324,7 +3363,7 @@ got_row: goto normal_return; next_rec: - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ /* PHASE 5: Move the cursor to the next index record */ if (mtr_has_extra_clust_latch) { diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index 91aaba40812..5395f5160e4 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -59,7 +59,6 @@ row_vers_impl_x_locked_off_kernel( ibool rec_del; ulint err; mtr_t mtr; - char err_buf[1000]; ut_ad(mutex_own(&kernel_mutex)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); @@ -77,22 +76,17 @@ row_vers_impl_x_locked_off_kernel( clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr); if (!clust_rec) { - rec_sprintf(err_buf, 900, rec); - - ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: cannot find the clustered index record\n" -"InnoDB: for a secondary index record in table %s index %s.\n" -"InnoDB: Secondary index record %s.\n" -"InnoDB: The table is probably corrupt. Please run CHECK TABLE on it.\n" -"InnoDB: You can try to repair the table by dump + drop + reimport.\n" -"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n", - index->table_name, index->name, err_buf); - mutex_enter(&kernel_mutex); - mtr_commit(&mtr); - - /* We assume there is no lock on the record, though this - is not certain because the table is apparently corrupt */ + /* In a rare case it is possible that no clust rec is found + for a secondary index record: if in row0umod.c + row_undo_mod_remove_clust_low() we have already removed the + clust rec, while purge is still cleaning and removing + secondary index records associated with earlier versions of + the clustered index record. In that case there cannot be + any implicit lock on the secondary index record, because + an active transaction which has modified the secondary index + record has also modified the clustered index record. And in + a rollback we always undo the modifications to secondary index + records before the clustered index record. */ return(NULL); } From fb94c5810c55fa1e33b084e3f9b2cecc7abe2a99 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 03:38:09 +0300 Subject: [PATCH 05/28] row0sel.c, row0ins.c: Fix error in previous push innobase/row/row0ins.c: Fix error in previous push innobase/row/row0sel.c: Fix error in previous push --- innobase/row/row0ins.c | 6 ++++-- innobase/row/row0sel.c | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index d36e5a9761e..e02859bc851 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -792,8 +792,10 @@ row_ins_foreign_check_on_constraint( clust_rec = btr_pcur_get_rec(cascade->pcur); - if (btr_pcur_get_low_match(cascade->pcur) - < dict_index_get_n_unique(clust_index)) { + if (!page_rec_is_user_rec(clust_rec) + || btr_pcur_get_low_match(cascade->pcur) + < dict_index_get_n_unique(clust_index)) { + fprintf(stderr, "InnoDB: error in cascade of a foreign key op\n" "InnoDB: index %s table %s\n", index->name, diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index afc01247347..a263de74e3e 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -609,8 +609,12 @@ row_sel_get_clust_rec( clust_rec = btr_pcur_get_rec(&(plan->clust_pcur)); - if (btr_pcur_get_low_match(&(plan->clust_pcur)) - < dict_index_get_n_unique(index)) { + /* Note: only if the search ends up on a non-infimum record is the + low_match value the real match to the search tuple */ + + if (!page_rec_is_user_rec(clust_rec) + || btr_pcur_get_low_match(&(plan->clust_pcur)) + < dict_index_get_n_unique(index)) { ut_a(rec_get_deleted_flag(rec)); ut_a(node->read_view); @@ -2322,8 +2326,12 @@ row_sel_get_clust_rec_for_mysql( clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); - if (btr_pcur_get_low_match(prebuilt->clust_pcur) - < dict_index_get_n_unique(clust_index)) { + /* Note: only if the search ends up on a non-infimum record is the + low_match value the real match to the search tuple */ + + if (!page_rec_is_user_rec(clust_rec) + || btr_pcur_get_low_match(prebuilt->clust_pcur) + < dict_index_get_n_unique(clust_index)) { /* In a rare case it is possible that no clust rec is found for a delete-marked secondary index record: if in row0umod.c From 1fe55eb4ee7e2a4d965f4e295dc62e65211000f6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 03:49:34 +0300 Subject: [PATCH 06/28] row0vers.c: Add forgotten mtr_commit() innobase/row/row0vers.c: Add forgotten mtr_commit() --- innobase/row/row0vers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index 5395f5160e4..1e9cef4c726 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -88,6 +88,8 @@ row_vers_impl_x_locked_off_kernel( a rollback we always undo the modifications to secondary index records before the clustered index record. */ + mtr_commit(&mtr); + return(NULL); } From aee336f42dd19232a5a1bc37d9d617284dd479b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 03:53:18 +0300 Subject: [PATCH 07/28] row0vers.c: Add forgotten mutex_enter() innobase/row/row0vers.c: Add forgotten mutex_enter() --- innobase/row/row0vers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index 1e9cef4c726..d4a463d8a96 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -88,6 +88,7 @@ row_vers_impl_x_locked_off_kernel( a rollback we always undo the modifications to secondary index records before the clustered index record. */ + mutex_enter(&kernel_mutex); mtr_commit(&mtr); return(NULL); From 92542bb071c9411f35f6b5d3445d6801724f332e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 22:08:04 +0200 Subject: [PATCH 08/28] - Added /usr/lib64 to the path to search for libssl.a (required on AMD64) - fixed a typo --- acinclude.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 4d7900acc3d..abeb2024f4a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -711,7 +711,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ done for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ -/usr/lib /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do +/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do if test -f $d/libssl.a ; then OPENSSL_LIB=$d fi @@ -721,7 +721,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ echo "Could not find an installation of OpenSSL" if test -n "$OPENSSL_LIB" ; then if test "$IS_LINUX" = "true"; then - echo "Looks like you've forgotted to install OpenSSL development RPM" + echo "Looks like you've forgotten to install OpenSSL development RPM" fi fi exit 1 From 725a4c39d2815315a1b2aa40bc2ce6bb54d3b828 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 01:05:24 +0300 Subject: [PATCH 09/28] page0page.c: Track an assertion failure reported on the mailing list June 18th, 2003 innobase/page/page0page.c: Track an assertion failure reported on the mailing list June 18th, 2003 --- innobase/page/page0page.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index ef5dad60c08..e087941a970 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -446,7 +446,6 @@ page_copy_rec_list_end_no_locks( page_cur_move_to_next(&cur1); } - /* Track a memory corruption bug in Windows */ ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == PAGE_INFIMUM); page_cur_set_before_first(new_page, &cur2); @@ -456,11 +455,23 @@ page_copy_rec_list_end_no_locks( sup = page_get_supremum_rec(page); while (sup != page_cur_get_rec(&cur1)) { - ut_a( - page_cur_rec_insert(&cur2, page_cur_get_rec(&cur1), mtr)); + if (!page_cur_rec_insert(&cur2, + page_cur_get_rec(&cur1), mtr)) { + /* Track an assertion failure reported on the mailing + list on June 18th, 2003 */ + + buf_page_print(new_page); + buf_page_print(page); + ut_print_timestamp(stderr); + + fprintf(stderr, +"InnoDB: rec offset %lu, cur1 offset %lu, cur2 offset %lu\n", + (ulint)(rec - page), + (ulint)(page_cur_get_rec(&cur1) - page), + (ulint)(page_cur_get_rec(&cur2) - new_page)); + ut_a(0); + } - ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) - == PAGE_INFIMUM); page_cur_move_to_next(&cur1); page_cur_move_to_next(&cur2); } From 85d2282e257ba47555fc05ef62dc70ece5b7a69e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 14:02:19 +0500 Subject: [PATCH 10/28] SCRUM Task ID 894: Backport default_week_format variable to 4.0 mysql-test/r/func_time.result: Backport default_week_format variable to 4.0 mysql-test/t/func_time.test: Backport default_week_format variable to 4.0 sql/mysqld.cc: Backport default_week_format variable to 4.0 sql/set_var.cc: Backport default_week_format variable to 4.0 sql/sql_class.h: Backport default_week_format variable to 4.0 sql/sql_yacc.yy: Backport default_week_format variable to 4.0 --- mysql-test/r/func_time.result | 5 +++++ mysql-test/t/func_time.test | 4 ++++ sql/mysqld.cc | 8 +++++++- sql/set_var.cc | 4 ++++ sql/sql_class.h | 1 + sql/sql_yacc.yy | 6 +++++- 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 06c0be86667..58a05a2336f 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -96,6 +96,11 @@ week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3) select week(20001231,2),week(20001231,3); week(20001231,2) week(20001231,3) 1 52 +set default_week_format = 2; +select week(20001231),week(20001231,2),week(20001231,0); +week(20001231) week(20001231,2) week(20001231,0) +1 1 53 +set default_week_format = 0; select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v'); date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v') 1998-53 1998-53 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 3057729ab96..a51869e7d76 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -39,6 +39,10 @@ select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', y select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3); select week(20001231,2),week(20001231,3); +set default_week_format = 2; +select week(20001231),week(20001231,2),week(20001231,0); +set default_week_format = 0; + select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v'); select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v'); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0f3500248c0..2e6e226b18e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3179,7 +3179,8 @@ enum options { OPT_BDB_CACHE_SIZE, OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, - OPT_ERROR_LOG_FILE + OPT_ERROR_LOG_FILE, + OPT_DEFAULT_WEEK_FORMAT }; @@ -3988,6 +3989,11 @@ replicating a LOAD DATA INFILE command", (gptr*) &global_system_variables.net_wait_timeout, (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, + { "default-week-format", OPT_DEFAULT_WEEK_FORMAT, + "The default week format used by WEEK() functions.", + (gptr*) &global_system_variables.default_week_format, + (gptr*) &max_system_variables.default_week_format, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/set_var.cc b/sql/set_var.cc index 1da187598c4..32603ec51d9 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -296,6 +296,8 @@ static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter static sys_var_rand_seed1 sys_rand_seed1("rand_seed1"); static sys_var_rand_seed2 sys_rand_seed2("rand_seed2"); +static sys_var_thd_ulong sys_default_week_format("default_week_format", + &SV::default_week_format); /* List of all variables for initialisation and storage in hash @@ -316,6 +318,7 @@ sys_var *sys_variables[]= &sys_bulk_insert_buff_size, &sys_concurrent_insert, &sys_connect_timeout, + &sys_default_week_format, &sys_convert_charset, &sys_delay_key_write, &sys_delayed_insert_limit, @@ -421,6 +424,7 @@ struct show_var_st init_vars[]= { {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, {sys_convert_charset.name, (char*) &sys_convert_charset, SHOW_SYS}, {"datadir", mysql_real_data_home, SHOW_CHAR}, + {"default_week_format", (char*) &sys_default_week_format, SHOW_SYS}, {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS}, {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS}, {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS}, diff --git a/sql/sql_class.h b/sql/sql_class.h index 9857774fb84..a8a24451ecc 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -309,6 +309,7 @@ struct system_variables ulong tmp_table_size; ulong tx_isolation; ulong table_type; + ulong default_week_format; my_bool log_warnings; my_bool low_priority_updates; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4a41ad32dcc..0ff09a52a9e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2002,7 +2002,11 @@ simple_expr: | USER '(' ')' { $$= new Item_func_user(); current_thd->safe_to_cache_query=0; } | WEEK_SYM '(' expr ')' - { $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); } + { + LEX *lex=Lex; + $$= new Item_func_week($3,new Item_int((char*) "0", + lex->thd->variables.default_week_format,1)); + } | WEEK_SYM '(' expr ',' expr ')' { $$= new Item_func_week($3,$5); } | YEAR_SYM '(' expr ')' From 4eef86c60b0439eb612c2d3ab764c10f8e6cd0c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 15:38:52 +0500 Subject: [PATCH 11/28] Fix for bug #616 mysqld crash / SSL with SQLyog --- sql/sql_parse.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bb06713ec4c..3b3da6d35b3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -583,6 +583,11 @@ check_connections(THD *thd) if (thd->client_capabilities & CLIENT_SSL) { /* Do the SSL layering. */ + if (!ssl_acceptor_fd) + { + inc_host_errors(&thd->remote.sin_addr); + return(ER_HANDSHAKE_ERROR); + } DBUG_PRINT("info", ("IO layer change in progress...")); if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout)) { From 332334e837331cecb5344e3cbd2c91dc3d0cbca9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 12:38:14 -0400 Subject: [PATCH 12/28] Fix error msg. Bug #681 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/nt_servc.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 092b6f3f2a5..9a826cffbfc 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -44,6 +44,7 @@ jorge@linux.jorge.mysql.com kaj@work.mysql.com lenz@kallisto.mysql.com lenz@mysql.com +miguel@hegel.(none) miguel@hegel.br miguel@hegel.local miguel@light. diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index b917c91ce15..b18d3d00d88 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -462,7 +462,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType) { /* a remove operation */ if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS ))) - printf("The service doesn't exists!\n"); + printf("The service doesn't exist!\n"); else { SERVICE_STATUS ss; From a7425f5ade8e9145b4bbe1107b5d32c163b71d32 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 13:54:22 +0200 Subject: [PATCH 13/28] Warn that --log-slave-updates is used without --log-bin and disabled (WL#998) sql/mysqld.cc: Warn that --log-slave-updates is used without --log-bin and disabled. --- sql/mysqld.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0f3500248c0..318128f77e4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2322,6 +2322,12 @@ The server will not act as a slave."); opt_binlog_index_name,LOG_BIN); using_update_log=1; } + else if (opt_log_slave_updates) + { + sql_print_error("\ +Warning: you need to use --log-bin to make --log-slave-updates work. \ +Now disabling --log-slave-updates."); + } if (opt_bootstrap) { From 4161b5a633dc9d8b1f8e2a9ae384f514336b48d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 15:19:51 +0200 Subject: [PATCH 14/28] - added $(EXEEXT) to gen_lex_hash generation/execution to fix a build problem on Windows/cygwin (BUG#668) --- sql/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index a589f1379f9..e2494e50d96 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -114,8 +114,8 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(CXXCOMPILE) $(LM_CFLAGS) -c $< lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h - $(MAKE) gen_lex_hash - ./gen_lex_hash > $@ + $(MAKE) gen_lex_hash$(EXEEXT) + ./gen_lex_hash$(EXEEXT) > $@ # Hack to ensure that lex_hash.h is built early sql_lex.o: lex_hash.h From 656fdcc722c67706b897444e5b33312d609957cb Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 15:48:52 +0200 Subject: [PATCH 15/28] fix for BUG#691 (4.0 mysqlbinlog couldn't read 3.23 binlog). Safe parenthesis. --- client/mysqlbinlog.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 75b875b4f4e..9ef340197a7 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -396,8 +396,8 @@ static int check_header(IO_CACHE* file) if (buf[4] == START_EVENT) { uint event_len; - event_len = uint4korr(buf + 4); - old_format = (event_len < LOG_EVENT_HEADER_LEN + START_HEADER_LEN); + event_len = uint4korr(buf + EVENT_LEN_OFFSET); + old_format = (event_len < (LOG_EVENT_HEADER_LEN + START_HEADER_LEN)); } } my_b_seek(file, pos); From 3e897bc3b6b838fe4b91d0ee4148d4b6c530c20d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 20:04:52 +0500 Subject: [PATCH 16/28] Fix for bug #666 (Nice number, yeah?) sql/item_strfunc.cc: Item_func_elt::valXXX() functions don't expect NULL argument if it is not the first one. --- sql/item_strfunc.cc | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 208be1ecd7f..9d4f7641b1d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1539,37 +1539,46 @@ void Item_func_elt::update_used_tables() double Item_func_elt::val() { uint tmp; + null_value=1; if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) - { - null_value=1; return 0.0; - } + + double result= args[tmp-1]->val(); + if (args[tmp-1]->is_null()) + return 0.0; + null_value=0; - return args[tmp-1]->val(); + return result; } longlong Item_func_elt::val_int() { uint tmp; + null_value=1; if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) - { - null_value=1; return 0; - } + + int result= args[tmp-1]->val_int(); + if (args[tmp-1]->is_null()) + return 0; + null_value=0; - return args[tmp-1]->val_int(); + return result; } String *Item_func_elt::val_str(String *str) { uint tmp; + null_value=1; if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) - { - null_value=1; return NULL; - } + + String *result= args[tmp-1]->val_str(str); + if (args[tmp-1]->is_null()) + return NULL; + null_value=0; - return args[tmp-1]->val_str(str); + return result; } From 1688ada0e2ce3bf5e62f1539811f0cfb0d8bc4b6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Jun 2003 16:59:40 +0500 Subject: [PATCH 17/28] Proposed fix for #674 This crash happens in rather exotic case when we try to run SELECT DISTINCT some_func(SUM(some_field)) GROUP BY another_field; on a table with single row. Optimizer marks this table as const, sets group=NULL (with remove_const) thus, create_tmp_table makes mistake collecting columns for temporary table and then crashes because the field_count gets less than hidden_columns_count. sql/sql_select.cc: There's several ways to fix this bug. This one looks easy and correct to me --- sql/sql_select.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0e8b191e4ef..cb056100e2a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -453,6 +453,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, goto err; thd->proc_info="preparing"; + + select_distinct= select_distinct && (join.const_tables != join.tables); + if (result->initialize_tables(&join)) goto err; if (join.const_table_map != join.found_const_table_map && From 5c9b87ce08a1651c6a26509cd2e65a23a20d2cc7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Jun 2003 18:10:59 +0200 Subject: [PATCH 18/28] Always send a fake Rotate event (this is roughly 70 bytes) when starting binlog_dump. This way 3.23.58 slaves will always detect a 4.0.14 master (and stop) immediately. BUG#198. mysql-test/r/rpl_log.result: result update (the relay log now contains a fake Rotate_log_event). mysql-test/r/rpl_log_pos.result: result update (the relay log now contains a fake Rotate_log_event). --- mysql-test/r/rpl_log.result | 2 +- mysql-test/r/rpl_log_pos.result | 2 +- sql/sql_repl.cc | 43 ++++++++++++++++++++++----------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 425c376af1e..316bf1f3dd0 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -93,6 +93,6 @@ slave-bin.002 62 Query 1 168 use test; insert into t1 values (1) slave-bin.002 122 Query 1 228 use test; drop table t1 show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space -127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1522 master-bin.002 Yes Yes 0 0 276 1526 +127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1563 master-bin.002 Yes Yes 0 0 276 1567 show binlog events in 'slave-bin.005' from 4; Error when executing command SHOW BINLOG EVENTS: Could not find target log diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result index e76b565813f..3224e84fa31 100644 --- a/mysql-test/r/rpl_log_pos.result +++ b/mysql-test/r/rpl_log_pos.result @@ -21,7 +21,7 @@ Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Lo slave start; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space -127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 No Yes 0 0 73 4 +127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 45 master-bin.001 No Yes 0 0 73 45 slave stop; change master to master_log_pos=173; slave start; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index e3af076da1f..a3cfe442b0f 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -51,7 +51,7 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg) } static int fake_rotate_event(NET* net, String* packet, char* log_file_name, - const char**errmsg) + ulonglong position, const char**errmsg) { char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN]; memset(header, 0, 4); // when does not matter @@ -69,7 +69,7 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, packet->append(header, sizeof(header)); /* We need to split the next statement because of problem with cxx */ - int4store(buf,4); // tell slave to skip magic number + int4store(buf,position); int4store(buf+4,0); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p,ident_len); @@ -382,17 +382,30 @@ impossible position"; */ packet->set("\0", 1); - // if we are at the start of the log - if (pos == BIN_LOG_HEADER_SIZE) + /* + Before 4.0.14 we called fake_rotate_event below only if + (pos == BIN_LOG_HEADER_SIZE), because if this is false then the slave + already knows the binlog's name. + Now we always call fake_rotate_event; if the slave already knew the log's + name (ex: CHANGE MASTER TO MASTER_LOG_FILE=...) this is useless but does not + harm much. It is nice for 3.23 (>=.58) slaves which test Rotate events + to see if the master is 4.0 (then they choose to stop because they can't + replicate 4.0); by always calling fake_rotate_event we are sure that 3.23.58 + and newer will detect the problem as soon as replication starts (BUG#198). + Always calling fake_rotate_event makes sending of normal + (=from-binlog) Rotate events a priori unneeded, but it is not so simple: the + 2 Rotate events are not equivalent, the normal one is before the Stop event, + the fake one is after. If we don't send the normal one, then the Stop event + will be interpreted (by existing 4.0 slaves) as "the master stopped", which + is wrong. So for safety, given that we want minimum modification of 4.0, we + send the normal and fake Rotates. + */ + if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg)) { - // tell the client log name with a fake rotate_event - if (fake_rotate_event(net, packet, log_file_name, &errmsg)) - { - my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; - goto err; - } - packet->set("\0", 1); + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; + goto err; } + packet->set("\0", 1); while (!net->error && net->vio != 0 && !thd->killed) { @@ -585,10 +598,12 @@ Increase max_allowed_packet on master"; end_io_cache(&log); (void) my_close(file, MYF(MY_WME)); - // fake Rotate_log event just in case it did not make it to the log - // otherwise the slave make get confused about the offset + /* + Even if the previous log contained a Rotate_log_event, we still fake + one. + */ if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 || - fake_rotate_event(net, packet, log_file_name, &errmsg)) + fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE, &errmsg)) { my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; From f403da4bf2dba7f21c1076d986c73ef5d1ce2025 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Jun 2003 14:10:46 +0200 Subject: [PATCH 19/28] Fixed cleanup_load_tmpdir() which deleted nothing. sql/log_event.cc: - cleanup_load_tmpdir() did not work at all because it forgot to indicate the directory part of the path when calling my_delete(). - A misplaced R_POS_OFFSET (fortunately this was no bug as this constant is 0). sql/sql_repl.cc: - fix fake_rotate_event() for pos>4G (correction of a change I pushed yesterday). --- sql/log_event.cc | 9 ++++++--- sql/sql_repl.cc | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index ff968babcf0..727b2052969 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -168,12 +168,15 @@ static void cleanup_load_tmpdir() uint i; if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME)))) return; - + char fname[FN_REFLEN]; for (i=0 ; i < (uint)dirp->number_off_files; i++) { file=dirp->dir_entry+i; if (is_prefix(file->name,"SQL_LOAD-")) - my_delete(file->name, MYF(0)); + { + fn_format(fname,file->name,slave_load_tmpdir,"",0); + my_delete(fname, MYF(0)); + } } my_dirend(dirp); @@ -813,7 +816,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len, int Rotate_log_event::write_data(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; - int8store(buf, pos + R_POS_OFFSET); + int8store(buf + R_POS_OFFSET, pos); return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index a3cfe442b0f..d0ed1a19d96 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -68,9 +68,12 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, int4store(header + LOG_POS_OFFSET, 0); packet->append(header, sizeof(header)); - /* We need to split the next statement because of problem with cxx */ - int4store(buf,position); - int4store(buf+4,0); + /* + An old comment said talked about a need for splitting the int8store below + into 2 int4store because of a problem with cxx; I can't understand that as + we already use int8store in Rotatel_log_event::write_data(). + */ + int8store(buf+R_POS_OFFSET,position); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p,ident_len); if (my_net_write(net, (char*)packet->ptr(), packet->length())) From e0be1a89304afb756b9df8118612dc79cc13912e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Jun 2003 16:20:06 +0300 Subject: [PATCH 20/28] dict0dict.h, dict0dict.c, ha_innodb.cc: In ORDER BY MySQL seems to set the key read flag also in the case where the primary key contains only a prefix of a column - not the whole column; to prevent potential bugs retrieve the whole column if the index contains a prefix of it sql/ha_innodb.cc: In ORDER BY MySQL seems to set the key read flag also in the case where the primary key contains only a prefix of a column - not the whole column; to prevent potential bugs retrieve the whole column if the index contains a prefix of it innobase/dict/dict0dict.c: In ORDER BY MySQL seems to set the key read flag also in the case where the primary key contains only a prefix of a column - not the whole column; to prevent potential bugs retrieve the whole column if the index contains a prefix of it innobase/include/dict0dict.h: In ORDER BY MySQL seems to set the key read flag also in the case where the primary key contains only a prefix of a column - not the whole column; to prevent potential bugs retrieve the whole column if the index contains a prefix of it --- innobase/dict/dict0dict.c | 40 ++++++++++++++++++++++++++++++++++++ innobase/include/dict0dict.h | 10 +++++++++ sql/ha_innodb.cc | 11 ++++++---- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 2fc05b1923f..b1d7b5f762e 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -494,6 +494,46 @@ dict_index_get_nth_col_pos( return(ULINT_UNDEFINED); } +/************************************************************************ +Returns TRUE if the index contains a column or a prefix of that column. */ + +ibool +dict_index_contains_col_or_prefix( +/*==============================*/ + /* out: TRUE if contains the column or its + prefix */ + dict_index_t* index, /* in: index */ + ulint n) /* in: column number */ +{ + dict_field_t* field; + dict_col_t* col; + ulint pos; + ulint n_fields; + + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + if (index->type & DICT_CLUSTERED) { + + return(TRUE); + } + + col = dict_table_get_nth_col(index->table, n); + + n_fields = dict_index_get_n_fields(index); + + for (pos = 0; pos < n_fields; pos++) { + field = dict_index_get_nth_field(index, pos); + + if (col == field->col) { + + return(TRUE); + } + } + + return(FALSE); +} + /************************************************************************ Looks for a matching field in an index. The column and the prefix len have to be the same. */ diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index e88c6a52bcb..b5ec5381db2 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -569,6 +569,16 @@ dict_index_get_nth_col_pos( dict_index_t* index, /* in: index */ ulint n); /* in: column number */ /************************************************************************ +Returns TRUE if the index contains a column or a prefix of that column. */ + +ibool +dict_index_contains_col_or_prefix( +/*==============================*/ + /* out: TRUE if contains the column or its + prefix */ + dict_index_t* index, /* in: index */ + ulint n); /* in: column number */ +/************************************************************************ Looks for a matching field in an index. The column and the prefix len has to be the same. */ diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 795cffc0776..a6528209b3e 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1863,7 +1863,11 @@ build_template( if (prebuilt->read_just_key) { /* MySQL has instructed us that it is enough to - fetch the columns in the key */ + fetch the columns in the key; looks like MySQL + can set this flag also when there is only a + prefix of the column in the key: in that case we + retrieve the whole column from the clustered + index */ fetch_all_in_key = TRUE; } else { @@ -1924,9 +1928,8 @@ build_template( field = table->field[i]; if (templ_type == ROW_MYSQL_REC_FIELDS - && !(fetch_all_in_key && - ULINT_UNDEFINED != dict_index_get_nth_col_pos( - index, i)) + && !(fetch_all_in_key + && dict_index_contains_col_or_prefix(index, i)) && thd->query_id != field->query_id && thd->query_id != (field->query_id ^ MAX_ULONG_BIT) && thd->query_id != From 616f46df415783c35b4c3d5d8352fd1f01faf554 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 13:03:04 +0300 Subject: [PATCH 21/28] Added analyze as alias for optimize --- sql/ha_innodb.cc | 6 ++++++ sql/ha_innodb.h | 1 + 2 files changed, 7 insertions(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index fd030fff091..72267f2426c 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3847,6 +3847,12 @@ ha_innobase::analyze( return(0); } + +int ha_innobase::optimize(THD* thd, HA_CHECK_OPT* check_opt) +{ + return ha_innobase::analyze(thd,check_opt); +} + /*********************************************************************** Tries to check that an InnoDB table is not corrupted. If corruption is noticed, prints to stderr information about it. In case of corruption diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 1a9b1b16c64..3f354a2fa11 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -153,6 +153,7 @@ class ha_innobase: public handler void position(const byte *record); void info(uint); int analyze(THD* thd,HA_CHECK_OPT* check_opt); + int optimize(THD* thd,HA_CHECK_OPT* check_opt); int extra(enum ha_extra_function operation); int reset(void); int external_lock(THD *thd, int lock_type); From 09c7b48d43b13d7e292b79b8abd2ed2a1490715f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 12:48:55 +0200 Subject: [PATCH 22/28] fixed bug in references column grants BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/sql_acl.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 092b6f3f2a5..9975c883180 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -84,6 +84,7 @@ sasha@mysql.sashanet.com serg@build.mysql2.com serg@serg.mylan serg@serg.mysql.com +serg@sergbook.mylan serg@sergbook.mysql.com sinisa@rhols221.adsl.netsonic.fi tfr@beta.frontier86.ee diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 1d074fe6001..f3fdf950a12 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -76,8 +76,8 @@ #define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6)) #define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) #define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) -#define fix_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) << 7)) -#define get_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) >> 7)) +#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 7)) +#define get_rights_for_column(A) (((A) & 7) | (((A) & ~7) >> 7)) /* prototypes */ From 35c2b9df7564c95c38f04fc4dbc3bebea81a9a41 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 20:03:59 +0300 Subject: [PATCH 23/28] SHOW GRANTS hided real grants when grants on both column and table (Bug 654) mysql-test/r/grant.result: Test of grant BUG mysql-test/t/grant.test: Test of grant BUG sql/sql_acl.cc: SHOW GRANTS hided real grants when grants on both column and table (Bug 654) Code cleanup (Bigger than intended because of editor problem) sql/sql_acl.h: Fixed grant bug --- mysql-test/r/grant.result | 47 ++++- mysql-test/t/grant.test | 34 +++- sql/sql_acl.cc | 361 +++++++++++++++++++++----------------- sql/sql_acl.h | 4 +- 4 files changed, 279 insertions(+), 167 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index c1dcd5c29e9..76080c85511 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1,3 +1,4 @@ +drop table if exists t1; delete from mysql.user where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1'; flush privileges; @@ -64,8 +65,44 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TE revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; flush privileges; -grant usage on test.* to user@localhost with grant option; -show grants for user@localhost; -Grants for user@localhost -GRANT USAGE ON *.* TO 'user'@'localhost' -GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION +grant usage on test.* to mysqltest_1@localhost with grant option; +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT USAGE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION +GRANT USAGE ON `test`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION +delete from mysql.user where user='mysqltest_1'; +delete from mysql.db where user='mysqltest_1'; +delete from mysql.tables_priv where user='mysqltest_1'; +delete from mysql.columns_priv where user='mysqltest_1'; +flush privileges; +create table t1 (a int); +GRANT select,update,insert on t1 to mysqltest_1@localhost; +GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT SELECT, SELECT (a), INSERT, INSERT (a), UPDATE, UPDATE (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost' +select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; +table_priv column_priv +Select,Insert,Update Select,Insert,Update,References +REVOKE select (a), update on t1 from mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT SELECT, INSERT, INSERT (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost' +REVOKE insert,insert (a) on t1 from mysqltest_1@localhost; +GRANT references on t1 to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT SELECT, REFERENCES, REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost' +select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; +table_priv column_priv +Select,References References +delete from mysql.user where user='mysqltest_1'; +delete from mysql.db where user='mysqltest_1'; +delete from mysql.tables_priv where user='mysqltest_1'; +delete from mysql.columns_priv where user='mysqltest_1'; +flush privileges; +drop table t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index bd04b2e4c41..b18ae941c26 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1,3 +1,7 @@ +--disable_warnings +drop table if exists t1; +--enable_warnings + # # Test that SSL options works properly # @@ -39,6 +43,32 @@ show grants for mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; flush privileges; -grant usage on test.* to user@localhost with grant option; -show grants for user@localhost; +grant usage on test.* to mysqltest_1@localhost with grant option; +show grants for mysqltest_1@localhost; +delete from mysql.user where user='mysqltest_1'; +delete from mysql.db where user='mysqltest_1'; +delete from mysql.tables_priv where user='mysqltest_1'; +delete from mysql.columns_priv where user='mysqltest_1'; +flush privileges; +# +# Test what happens when you have same table and colum level grants +# + +create table t1 (a int); +GRANT select,update,insert on t1 to mysqltest_1@localhost; +GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; +REVOKE select (a), update on t1 from mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +REVOKE insert,insert (a) on t1 from mysqltest_1@localhost; +GRANT references on t1 to mysqltest_1@localhost; +show grants for mysqltest_1@localhost; +select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; +delete from mysql.user where user='mysqltest_1'; +delete from mysql.db where user='mysqltest_1'; +delete from mysql.tables_priv where user='mysqltest_1'; +delete from mysql.columns_priv where user='mysqltest_1'; +flush privileges; +drop table t1; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f01248bb682..c93e082e0ff 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -193,7 +193,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) host.db= get_field(&mem, table,1); host.access= get_access(table,2); host.access= fix_rights_for_db(host.access); - host.sort= get_sort(2,host.host.hostname,host.db); + host.sort= get_sort(2,host.host.hostname,host.db); #ifndef TO_BE_REMOVED if (table->fields == 8) { // Without grant @@ -213,8 +213,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) if (table->field[2]->field_length == 8 && protocol_version == PROTOCOL_VERSION) { - sql_print_error( - "Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */ + sql_print_error("Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */ protocol_version=9; /* purecov: tested */ } @@ -247,7 +246,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) user.sort=get_sort(2,user.host.hostname,user.user); user.hostname_length= (user.host.hostname ? (uint) strlen(user.host.hostname) : 0); - if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ + if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ { char *ssl_type=get_field(&mem, table, 24); if (!ssl_type) @@ -259,7 +258,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) else /* !strcmp(ssl_type, "SPECIFIED") */ user.ssl_type=SSL_TYPE_SPECIFIED; - user.ssl_cipher= get_field(&mem, table, 25); + user.ssl_cipher= get_field(&mem, table, 25); user.x509_issuer= get_field(&mem, table, 26); user.x509_subject= get_field(&mem, table, 27); @@ -368,7 +367,14 @@ void acl_free(bool end) } } - /* Reload acl list if possible */ + +/* + Forget current privileges and read new privileges from the privilege tables + + SYNOPSIS + acl_reload() + thd Thread handle +*/ void acl_reload(THD *thd) { @@ -493,8 +499,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *message, - char **priv_user, char *priv_host, - bool old_ver, USER_RESOURCES *mqh) + char **priv_user, char *priv_host, + bool old_ver, USER_RESOURCES *mqh) { ulong user_access=NO_ACCESS; *priv_user=(char*) user; @@ -526,15 +532,15 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, { #ifdef HAVE_OPENSSL Vio *vio=thd->net.vio; - /* + /* In this point we know that user is allowed to connect from given host by given username/password pair. Now we check if SSL is required, if user is using SSL and if X509 certificate attributes are OK */ - switch (acl_user->ssl_type) { + switch (acl_user->ssl_type) { case SSL_TYPE_NOT_SPECIFIED: // Impossible - case SSL_TYPE_NONE: /* SSL is not required to connect */ + case SSL_TYPE_NONE: /* SSL is not required to connect */ user_access=acl_user->access; break; case SSL_TYPE_ANY: /* Any kind of SSL is good enough */ @@ -544,7 +550,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, case SSL_TYPE_X509: /* Client should have any valid certificate. */ /* We need to check for absence of SSL because without SSL - we should reject connection. + we should reject connection. */ if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_)) user_access=acl_user->access; @@ -653,12 +659,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length, } static void acl_update_user(const char *user, const char *host, - const char *password, + const char *password, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, const char *x509_subject, - USER_RESOURCES *mqh, + USER_RESOURCES *mqh, ulong privileges) { for (uint i=0 ; i < acl_users.elements ; i++) @@ -707,7 +713,7 @@ static void acl_update_user(const char *user, const char *host, static void acl_insert_user(const char *user, const char *host, - const char *password, + const char *password, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, @@ -805,9 +811,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db, } -/***************************************************************************** -** Get privilege for a host, user and db combination -*****************************************************************************/ + +/* + Get privilege for a host, user and db combination +*/ ulong acl_get(const char *host, const char *ip, const char *bin_ip, const char *user, const char *db) @@ -929,11 +936,14 @@ int wild_case_compare(const char *str,const char *wildstr) DBUG_RETURN (*str != '\0'); } -/***************************************************************************** -** check if there are any possible matching entries for this host -** All host names without wild cards are stored in a hash table, -** entries with wildcards are stored in a dynamic array -*****************************************************************************/ + +/* + Check if there are any possible matching entries for this host + + NOTES + All host names without wild cards are stored in a hash table, + entries with wildcards are stored in a dynamic array +*/ static void init_check_host(void) { @@ -1006,10 +1016,6 @@ bool acl_check_host(const char *host, const char *ip) return 1; // Host is not allowed } -/***************************************************************************** - Change password for the user if it's not an anonymous user - Note: This should write the error directly to the client! -*****************************************************************************/ /* Check if the user is allowed to change password @@ -1021,8 +1027,8 @@ bool acl_check_host(const char *host, const char *ip) user user name RETURN VALUE - 0 OK - 1 ERROR ; In this case the error is sent to the client. + 0 OK + 1 ERROR ; In this case the error is sent to the client. */ bool check_change_password(THD *thd, const char *host, const char *user) @@ -1061,7 +1067,7 @@ bool check_change_password(THD *thd, const char *host, const char *user) RETURN VALUES 0 ok 1 ERROR; In this case the error is sent to the client. -*/ +*/ bool change_password(THD *thd, const char *host, const char *user, char *new_password) @@ -1127,7 +1133,7 @@ find_acl_user(const char *host, const char *user) { ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),", - user,acl_user->user,(host),(acl_user->host))); + user,acl_user->user,(host),(acl_user->host))); if (!acl_user->user && !user[0] || acl_user->user && !strcmp(user,acl_user->user)) { @@ -1140,15 +1146,18 @@ find_acl_user(const char *host, const char *user) DBUG_RETURN(0); } -/***************************************************************************** - Handle comparing of hostname - A hostname may be of type: - hostname (May include wildcards); monty.pp.sci.fi - ip (May include wildcards); 192.168.0.0 - ip/netmask 192.168.0.0/255.255.255.0 - A net mask of 0.0.0.0 is not allowed. -*****************************************************************************/ +/* + Comparing of hostnames + + NOTES + A hostname may be of type: + hostname (May include wildcards); monty.pp.sci.fi + ip (May include wildcards); 192.168.0.0 + ip/netmask 192.168.0.0/255.255.255.0 + + A net mask of 0.0.0.0 is not allowed. +*/ static const char *calc_ip(const char *ip, long *val, char end) { @@ -1195,9 +1204,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, } -/**************************************************************************** - Code to update grants in the user and database privilege tables -****************************************************************************/ +/* + Update grants in the user and database privilege tables +*/ static bool update_user_table(THD *thd, const char *host, const char *user, const char *new_password) @@ -1263,7 +1272,7 @@ static bool test_if_create_new_users(THD *thd) /**************************************************************************** -** Handle GRANT commands + Handle GRANT commands ****************************************************************************/ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, @@ -1285,8 +1294,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, if (combo.password.length != HASH_PASSWORD_LENGTH) { my_printf_error(ER_PASSWORD_NO_MATCH, - "Password hash should be a %d-digit hexadecimal number", - MYF(0),HASH_PASSWORD_LENGTH); + "Password hash should be a %d-digit hexadecimal number", + MYF(0),HASH_PASSWORD_LENGTH); DBUG_RETURN(-1); } password=combo.password.str; @@ -1459,7 +1468,7 @@ static int replace_db_table(TABLE *table, const char *db, char what= (revoke_grant) ? 'N' : 'Y'; DBUG_ENTER("replace_db_table"); - // is there such a user in user table in memory ???? + /* Check if there is such a user in user table in memory? */ if (!initialized || !find_acl_user(combo.host.str,combo.user.str)) { my_error(ER_PASSWORD_NO_MATCH,MYF(0)); @@ -1471,7 +1480,7 @@ static int replace_db_table(TABLE *table, const char *db, table->field[2]->store(combo.user.str,combo.user.length); table->file->index_init(0); if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,0, - HA_READ_KEY_EXACT)) + HA_READ_KEY_EXACT)) { if (what == 'N') { // no row, no revoke @@ -1502,7 +1511,7 @@ static int replace_db_table(TABLE *table, const char *db, if (old_row_exists) { - // update old existing row + /* update old existing row */ if (rights) { if ((error=table->file->update_row(table->record[1],table->record[0]))) @@ -1529,11 +1538,11 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(0); /* This could only happen if the grant tables got corrupted */ - table_error: +table_error: table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->index_end(); - abort: +abort: DBUG_RETURN(-1); } @@ -1649,7 +1658,7 @@ public: if (!(mem_check = new GRANT_COLUMN(*res, fix_rights_for_column(priv)))) { - // Don't use this entry + /* Don't use this entry */ privs = cols = 0; /* purecov: deadcode */ return; /* purecov: deadcode */ } @@ -1827,7 +1836,7 @@ static int replace_column_table(GRANT_TABLE *g_t, key_length, HA_READ_KEY_EXACT)) goto end; - // Scan trough all rows with the same host,db,user and table + /* Scan through all rows with the same host,db,user and table */ do { ulong privileges = (ulong) table->field[6]->val_int(); @@ -1877,7 +1886,7 @@ static int replace_column_table(GRANT_TABLE *g_t, !key_cmp(table,key,0,key_length)); } - end: +end: table->file->index_end(); DBUG_RETURN(result); } @@ -1947,7 +1956,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, if (revoke_grant) { - // column rights are already fixed in mysql_table_grant ! + /* column rights are already fixed in mysql_table_grant */ store_table_rights=j & ~store_table_rights; } else @@ -1983,7 +1992,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, if (rights | col_rights) { grant_table->privs= rights; - grant_table->cols= col_rights; + grant_table->cols= col_rights; } else { @@ -1991,19 +2000,36 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } DBUG_RETURN(0); - /* This should never happen */ - table_error: + /* This should never happen */ +table_error: table->file->print_error(error,MYF(0)); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ } +/* + Store table level and column level grants in the privilege tables + + SYNOPSIS + mysql_table_grant() + thd Thread handle + table_list List of tables to give grant + user_list List of users to give grant + columns List of columns to give grant + rights Table level grant + revoke_grant Set to 1 if this is a REVOKE command + + RETURN + 0 ok + 1 error +*/ + int mysql_table_grant(THD *thd, TABLE_LIST *table_list, List &user_list, List &columns, ulong rights, bool revoke_grant) { - ulong column_priv = 0; + ulong column_priv= 0; List_iterator str_list (user_list); LEX_USER *Str; TABLE_LIST tables[3]; @@ -2024,21 +2050,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (columns.elements && !revoke_grant) { TABLE *table; - class LEX_COLUMN *check; - List_iterator iter(columns); + class LEX_COLUMN *column; + List_iterator column_iter(columns); if (!(table=open_ltable(thd,table_list,TL_READ))) DBUG_RETURN(-1); - while ((check = iter++)) + while ((column = column_iter++)) { - if (!find_field_in_table(thd,table,check->column.ptr(), - check->column.length(),0,0)) + if (!find_field_in_table(thd,table,column->column.ptr(), + column->column.length(),0,0)) { my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), - check->column.c_ptr(), table_list->alias); + column->column.c_ptr(), table_list->alias); DBUG_RETURN(-1); } - column_priv |= check->rights | (rights & COL_ACLS); + column_priv|= column->rights; } close_thread_tables(thd); } @@ -2148,21 +2174,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* If revoke_grant, calculate the new column privilege for tables_priv */ if (revoke_grant) { - class LEX_COLUMN *check; - List_iterator iter(columns); + class LEX_COLUMN *column; + List_iterator column_iter(columns); GRANT_COLUMN *grant_column; /* Fix old grants */ - while ((check = iter++)) + while ((column = column_iter++)) { grant_column = column_hash_search(grant_table, - check->column.ptr(), - check->column.length()); + column->column.ptr(), + column->column.length()); if (grant_column) - grant_column->rights&= ~(check->rights | rights); + grant_column->rights&= ~(column->rights | rights); } /* scan trough all columns to get new column grant */ - column_priv=0; + column_priv= 0; for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++) { grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns, @@ -2259,7 +2285,7 @@ int mysql_grant (THD *thd, const char *db, List &list, if (!revoke_grant) create_new_users= test_if_create_new_users(thd); - // go through users in user_list + /* go through users in user_list */ pthread_mutex_lock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); grant_version++; @@ -2280,7 +2306,7 @@ int mysql_grant (THD *thd, const char *db, List &list, continue; } if ((replace_user_table(thd, - tables[0].table, + tables[0].table, *Str, (!db ? rights : 0), revoke_grant, create_new_users))) @@ -2401,7 +2427,16 @@ end: } -/* Reload grant array if possible */ +/* + Reload grant array if possible + + SYNOPSIS + grant_reload() + thd Thread handler + + NOTES + Locked tables are checked by acl_init and doesn't have to be checked here +*/ void grant_reload(THD *thd) { @@ -2410,8 +2445,6 @@ void grant_reload(THD *thd) MEM_ROOT old_mem; DBUG_ENTER("grant_reload"); - // Locked tables are checked by acl_init and doesn't have to be checked here - pthread_mutex_lock(&LOCK_grant); grant_version++; old_hash_tables=hash_tables; @@ -2487,13 +2520,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, pthread_mutex_unlock(&LOCK_grant); return 0; - err: +err: pthread_mutex_unlock(&LOCK_grant); if (!no_errors) // Not a silent skip of table { const char *command=""; if (want_access & SELECT_ACL) - command ="select"; + command ="select"; else if (want_access & INSERT_ACL) command = "insert"; else if (want_access & UPDATE_ACL) @@ -2534,7 +2567,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name, pthread_mutex_lock(&LOCK_grant); - // reload table if someone has modified any grants + /* reload table if someone has modified any grants */ if (table->grant.version != grant_version) { @@ -2594,7 +2627,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) pthread_mutex_lock(&LOCK_grant); - // reload table if someone has modified any grants + /* reload table if someone has modified any grants */ if (table->grant.version != grant_version) { @@ -2604,7 +2637,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) table->real_name,0); /* purecov: inspected */ table->grant.version=grant_version; /* purecov: inspected */ } - // The following should always be true + /* The following should always be true */ if (!(grant_table=table->grant.grant_table)) goto err; /* purecov: inspected */ @@ -2619,7 +2652,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) return 0; /* We must use my_printf_error() here! */ - err: +err: pthread_mutex_unlock(&LOCK_grant); const char *command=""; @@ -2639,11 +2672,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) } -/**************************************************************************** +/* Check if a user has the right to access a database Access is accepted if he has a grant for any table in the database Return 1 if access is denied -****************************************************************************/ +*/ bool check_grant_db(THD *thd,const char *db) { @@ -2683,7 +2716,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) pthread_mutex_lock(&LOCK_grant); grant_table = table_hash_search(thd->host,thd->ip,db,user, - table->real_name,0); + table->real_name, 0); table->grant.grant_table=grant_table; // Remember for column test table->grant.version=grant_version; if (grant_table) @@ -2701,7 +2734,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) ulong priv; pthread_mutex_lock(&LOCK_grant); - // reload table if someone has modified any grants + /* reload table if someone has modified any grants */ if (table->grant.version != grant_version) { table->grant.grant_table= @@ -2726,11 +2759,20 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) return priv; } +/* Help function for mysql_show_grants */ -/***************************************************************************** - SHOW GRANTS : send to client grant-like strings depicting user@host - privileges -*****************************************************************************/ +static void add_user_option(String *grant, ulong value, const char *name) +{ + if (value) + { + char buff[22], *p; // just as in int2str + grant->append(' '); + grant->append(name, strlen(name)); + grant->append(' '); + p=int10_to_str(value, buff, 10); + grant->append(buff,p-buff); + } +} static const char *command_array[]= { @@ -2739,13 +2781,21 @@ static const char *command_array[]= "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT", }; + static uint command_lengths[]= { 6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18 }; -int mysql_show_grants(THD *thd,LEX_USER *lex_user) +/* + SHOW GRANTS; Send grants for a user to the client + + IMPLEMENTATION + Send to client grant-like strings depicting user@host privileges +*/ + +int mysql_show_grants(THD *thd,LEX_USER *lex_user) { ulong want_access; uint counter,index; @@ -2784,7 +2834,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) !my_strcasecmp(lex_user->host.str,host)) break; } - if (counter == acl_users.elements) + if (counter == acl_users.elements) { my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT), MYF(0),lex_user->user.str,lex_user->host.str); @@ -2815,13 +2865,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append("ALL PRIVILEGES",14); else if (!(want_access & ~GRANT_ACL)) global.append("USAGE",5); - else + else { bool found=0; ulong j,test_access= want_access & ~GRANT_ACL; for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1) { - if (test_access & j) + if (test_access & j) { if (found) global.append(", ",2); @@ -2831,7 +2881,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } global.append (" ON *.* TO '",12); - global.append(lex_user->user.str,lex_user->user.length); + global.append(lex_user->user.str,lex_user->user.length); global.append ("'@'",3); global.append(lex_user->host.str,lex_user->host.length); global.append ('\''); @@ -2854,25 +2904,25 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append(" REQUIRE ",9); if (acl_user->x509_issuer) { - ssl_options++; - global.append("ISSUER \'",8); - global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + ssl_options++; + global.append("ISSUER \'",8); + global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); global.append('\''); } if (acl_user->x509_subject) { - if (ssl_options++) - global.append(' '); - global.append("SUBJECT \'",9); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); + if (ssl_options++) + global.append(' '); + global.append("SUBJECT \'",9); + global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); global.append('\''); } if (acl_user->ssl_cipher) { - if (ssl_options++) - global.append(' '); - global.append("CIPHER '",8); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); + if (ssl_options++) + global.append(' '); + global.append("CIPHER '",8); + global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); global.append('\''); } } @@ -2880,30 +2930,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) (acl_user->user_resource.questions | acl_user->user_resource.updates | acl_user->user_resource.connections)) { - global.append(" WITH",5); + global.append(" WITH",5); if (want_access & GRANT_ACL) - global.append(" GRANT OPTION",13); - if (acl_user->user_resource.questions) - { - char buff[22], *p; // just as in int2str - global.append(" MAX_QUERIES_PER_HOUR ",22); - p=int10_to_str(acl_user->user_resource.questions,buff,10); - global.append(buff,p-buff); - } - if (acl_user->user_resource.updates) - { - char buff[22], *p; // just as in int2str - global.append(" MAX_UPDATES_PER_HOUR ",22); - p=int10_to_str(acl_user->user_resource.updates,buff,10); - global.append(buff,p-buff); - } - if (acl_user->user_resource.connections) - { - char buff[22], *p; // just as in int2str - global.append(" MAX_CONNECTIONS_PER_HOUR ",26); - p=int10_to_str(acl_user->user_resource.connections,buff,10); - global.append(buff,p-buff); - } + global.append(" GRANT OPTION",13); + add_user_option(&global, acl_user->user_resource.questions, + "MAX_QUERIES_PER_HOUR"); + add_user_option(&global, acl_user->user_resource.updates, + "MAX_UPDATES_PER_HOUR"); + add_user_option(&global, acl_user->user_resource.connections, + "MAX_CONNECTIONS_PER_HOUR"); } thd->packet.length(0); net_store_data(&thd->packet,global.ptr(),global.length()); @@ -2929,7 +2964,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) !my_strcasecmp(lex_user->host.str,host)) { want_access=acl_db->access; - if (want_access) + if (want_access) { String db(buff,sizeof(buff)); db.length(0); @@ -2938,7 +2973,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL))) db.append("ALL PRIVILEGES",14); else if (!(want_access & ~GRANT_ACL)) - db.append("USAGE",5); + db.append("USAGE",5); else { int found=0, cnt; @@ -2954,13 +2989,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } } - db.append (" ON `",5); + db.append(" ON `",5); db.append(acl_db->db); - db.append ("`.* TO '",8); - db.append(lex_user->user.str,lex_user->user.length); - db.append ("'@'",3); + db.append("`.* TO '",8); + db.append(lex_user->user.str,lex_user->user.length); + db.append("'@'",3); db.append(lex_user->host.str, lex_user->host.length); - db.append ('\''); + db.append('\''); if (want_access & GRANT_ACL) db.append(" WITH GRANT OPTION",18); thd->packet.length(0); @@ -2979,7 +3014,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) for (index=0 ; index < hash_tables.records ; index++) { const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index); + GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index); if (!(user=grant_table->user)) user=""; @@ -2989,44 +3024,54 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(lex_user->host.str,host)) { - want_access=grant_table->privs; - if ((want_access | grant_table->cols) != 0) + ulong table_access= grant_table->privs; + if ((table_access | grant_table->cols) != 0) { String global(buff,sizeof(buff)); global.length(0); global.append("GRANT ",6); - if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL))) + if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL))) global.append("ALL PRIVILEGES",14); - else + else { - int found=0; - ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL; + int found= 0; + ulong j,test_access= (table_access | grant_table->cols) & ~GRANT_ACL; - for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1) + for (counter= 0, j= SELECT_ACL; j <= TABLE_ACLS; counter++, j<<= 1) { - if (test_access & j) + if (test_access & j) { if (found) global.append(", ",2); - found = 1; + found= 1; global.append(command_array[counter],command_lengths[counter]); - if (grant_table->cols) + if (grant_table->cols) { - uint found_col=0; + uint found_col= 0; for (uint col_index=0 ; col_index < grant_table->hash_columns.records ; col_index++) { GRANT_COLUMN *grant_column = (GRANT_COLUMN*) hash_element(&grant_table->hash_columns,col_index); - if (grant_column->rights & j) + if (grant_column->rights & j) { - if (!found_col) + if (!found_col) { + found_col= 1; + /* + If we have a duplicated table level privilege, we + must write the access privilege name again. + */ + if (table_access & j) + { + global.append(", ", 2); + global.append(command_array[counter], + command_lengths[counter]); + } global.append(" (",2); - found_col=1; } else global.append(", ",2); @@ -3045,12 +3090,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append("`.`",3); global.append(grant_table->tname); global.append("` TO '",6); - global.append(lex_user->user.str,lex_user->user.length); + global.append(lex_user->user.str,lex_user->user.length); global.append("'@'",3); - global.append(lex_user->host.str,lex_user->host.length); + global.append(lex_user->host.str,lex_user->host.length); global.append('\''); - if (want_access & GRANT_ACL) - global.append(" WITH GRANT OPTION",18); + if (table_access & GRANT_ACL) + global.append(" WITH GRANT OPTION",18); thd->packet.length(0); net_store_data(&thd->packet,global.ptr(),global.length()); if (my_net_write(&thd->net,(char*) thd->packet.ptr(), @@ -3063,7 +3108,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } - end: +end: VOID(pthread_mutex_unlock(&acl_cache->lock)); pthread_mutex_unlock(&LOCK_grant); diff --git a/sql/sql_acl.h b/sql/sql_acl.h index f3fdf950a12..bf269e5a7e3 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -76,8 +76,8 @@ #define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6)) #define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) #define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) -#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 7)) -#define get_rights_for_column(A) (((A) & 7) | (((A) & ~7) >> 7)) +#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) +#define get_rights_for_column(A) (((A) & 7) | ((A) >> 8)) /* prototypes */ From 68524c81feac77d7d0e8dca716738b5b59d98e3f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 20:05:54 +0300 Subject: [PATCH 24/28] Simple code cleanup mysql-test/r/innodb.result: Fixed test case after innodb optimize->analyze fix mysys/mf_pack.c: Added comments sql/log_event.cc: Fixed usage of fn_format() sql/slave.cc: Indentation fixes and comments cleanup sql/sql_repl.cc: Comment cleanup --- mysql-test/r/innodb.result | 8 ++++---- mysys/mf_pack.c | 26 +++++++++++++++++++------- sql/log_event.cc | 6 +++--- sql/slave.cc | 32 +++++++++++++------------------- sql/sql_repl.cc | 5 ----- sql/sql_select.cc | 14 +++++++------- 6 files changed, 46 insertions(+), 45 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 9d1c232e830..465d4faf0bc 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -156,7 +156,7 @@ level id parent_id 1 1007 101 optimize table t1; Table Op Msg_type Msg_text -test.t1 optimize error The handler for the table doesn't support optimize +test.t1 optimize status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 0 PRIMARY 1 id A 87 NULL NULL BTREE @@ -180,7 +180,7 @@ create table t1 (a int) type=innodb; insert into t1 values (1), (2); optimize table t1; Table Op Msg_type Msg_text -test.t1 optimize error The handler for the table doesn't support optimize +test.t1 optimize status OK delete from t1 where a = 1; select * from t1; a @@ -712,7 +712,7 @@ world 2 hello 1 optimize table t1; Table Op Msg_type Msg_text -test.t1 optimize error The handler for the table doesn't support optimize +test.t1 optimize status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 0 PRIMARY 1 a A 2 NULL NULL BTREE @@ -1240,7 +1240,7 @@ t1 range c c 5 NULL 1 Using where update t1 set c=a; explain select * from t1 where c between 1 and 10000; table type possible_keys key key_len ref rows Extra -t1 ALL c NULL NULL NULL 29537 Using where +t1 ALL c NULL NULL NULL 27682 Using where drop table t1,t2; create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb; insert into t1 (id) values (null),(null),(null),(null),(null); diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 8fba14f626b..b3aa347006e 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -253,15 +253,27 @@ void symdirget(char *dir) } #endif /* USE_SYMDIR */ - /* Unpacks dirname to name that can be used by open... */ - /* Make that last char of to is '/' if from not empty and - from doesn't end in FN_DEVCHAR */ - /* Uses cleanup_dirname and changes ~/.. to home_dir/.. */ - /* Returns length of new directory */ + +/* + Fixes a directroy name so that can be used by open() + + SYNOPSIS + unpack_dirname() + to Store result here. May be = from + from 'Packed' directory name (may contain ~) + + IMPLEMENTATION + Make that last char of to is '/' if from not empty and + from doesn't end in FN_DEVCHAR + Uses cleanup_dirname and changes ~/.. to home_dir/.. + + Changes a UNIX filename to system filename (replaces / with \ on windows) + + RETURN + Length of new directory name (= length of to) +*/ uint unpack_dirname(my_string to, const char *from) - - /* to may be == from */ { uint length,h_length; char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; diff --git a/sql/log_event.cc b/sql/log_event.cc index 727b2052969..53289888242 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -100,7 +100,7 @@ static void pretty_print_str(String* packet, char* str, int len) static inline char* slave_load_file_stem(char*buf, uint file_id, int event_server_id) { - fn_format(buf,"SQL_LOAD-",slave_load_tmpdir,"",0); /* 4+32); */ + fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME); buf = strend(buf); buf = int10_to_str(::server_id, buf, 10); *buf++ = '-'; @@ -174,16 +174,16 @@ static void cleanup_load_tmpdir() file=dirp->dir_entry+i; if (is_prefix(file->name,"SQL_LOAD-")) { - fn_format(fname,file->name,slave_load_tmpdir,"",0); + fn_format(fname,file->name,slave_load_tmpdir,"",MY_UNPACK_FILENAME); my_delete(fname, MYF(0)); } } my_dirend(dirp); } - #endif + Log_event::Log_event(const char* buf, bool old_format) :temp_buf(0), cached_event_len(0), cache_stmt(0) { diff --git a/sql/slave.cc b/sql/slave.cc index 6c29d1a98bc..fe668900da0 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -134,7 +134,7 @@ int init_slave() goto err; } - if(init_master_info(active_mi,master_info_file,relay_log_info_file, + if (init_master_info(active_mi,master_info_file,relay_log_info_file, !master_host)) { sql_print_error("Failed to initialize the master info structure"); @@ -1777,18 +1777,17 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, pthread_mutex_lock(&data_lock); /* - This function will abort when it notices that - some CHANGE MASTER or RESET MASTER has changed - the master info. To catch this, these commands - modify abort_pos_wait ; we just monitor abort_pos_wait - and see if it has changed. - Why do we have this mechanism instead of simply monitoring slave_running in - the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that the - SQL thread be stopped? This is in case + This function will abort when it notices that some CHANGE MASTER or + RESET MASTER has changed the master info. + To catch this, these commands modify abort_pos_wait ; We just monitor + abort_pos_wait and see if it has changed. + Why do we have this mechanism instead of simply monitoring slave_running + in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that + the SQL thread be stopped? + This is becasue if someones does: STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE; - happens very quickly between the moment pthread_cond_wait() wakes up and - the while() is evaluated: in that case slave_running is again 1 when the - while() is evaluated. + the change may happen very quickly and we may not notice that + slave_running briefly switches between 1/0/1. */ init_abort_pos_wait= abort_pos_wait; @@ -1809,7 +1808,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, error= -2; //means improper arguments goto err; } - //p points to '.' + /* p points to '.' */ log_name_extension= strtoul(++p, &p_end, 10); /* p_end points to the first invalid character. @@ -1822,14 +1821,9 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, goto err; } - //"compare and wait" main loop + /* The "compare and wait" main loop */ while (!thd->killed && init_abort_pos_wait == abort_pos_wait && - /* - formerly we tested mi->slave_running, but what we care about is - rli->slave_running (because this concerns the SQL thread, while - mi->slave_running concerns the I/O thread). - */ slave_running) { bool pos_reached; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d0ed1a19d96..ae9bd8b7727 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -68,11 +68,6 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, int4store(header + LOG_POS_OFFSET, 0); packet->append(header, sizeof(header)); - /* - An old comment said talked about a need for splitting the int8store below - into 2 int4store because of a problem with cxx; I can't understand that as - we already use int8store in Rotatel_log_event::write_data(). - */ int8store(buf+R_POS_OFFSET,position); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p,ident_len); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0e8b191e4ef..67bec77e245 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1627,6 +1627,9 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) key_field->field->table->reginfo.not_exists_optimize=1; } + +#define FT_KEYPART (MAX_REF_PARTS+10) + static void add_ft_keys(DYNAMIC_ARRAY *keyuse_array, JOIN_TAB *stat,COND *cond,table_map usable_tables) @@ -1685,23 +1688,20 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array, } } - if (!cond_func || cond_func->key == NO_SUCH_KEY) - return; - - if (!(usable_tables & cond_func->table->map)) + if ((!cond_func || cond_func->key == NO_SUCH_KEY) || + (!(usable_tables & cond_func->table->map))) return; KEYUSE keyuse; - keyuse.table= cond_func->table; keyuse.val = cond_func; keyuse.key = cond_func->key; -#define FT_KEYPART (MAX_REF_PARTS+10) - keyuse.keypart=FT_KEYPART; + keyuse.keypart= FT_KEYPART; keyuse.used_tables=cond_func->key_item()->used_tables(); VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); } + static int sort_keyuse(KEYUSE *a,KEYUSE *b) { From 3d5f6a8867c848459191ba320b573bd832e51d5a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 23:32:07 +0300 Subject: [PATCH 25/28] Changed connect with timeout to use poll() instead if socket() to avoid problems with many open files --- libmysql/libmysql.c | 94 ++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c008d625900..3c8ac9f3387 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -40,14 +40,17 @@ #include #include #ifdef HAVE_SELECT_H -# include +#include #endif #ifdef HAVE_SYS_SELECT_H #include #endif +#ifdef HAVE_POLL +#include #endif +#endif /* !defined(MSDOS) && !defined(__WIN__) */ #ifdef HAVE_SYS_UN_H -# include +#include #endif #if defined(THREAD) && !defined(__WIN__) #include /* because of signal() */ @@ -148,9 +151,12 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host, const char* user, const char* passwd); +#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__)) +static int wait_for_data(my_socket fd, uint timeout); +#endif /**************************************************************************** - A modified version of connect(). connect2() allows you to specify + A modified version of connect(). my_connect() allows you to specify a timeout value, in seconds, that we should wait until we derermine we can't connect to a particular host. If timeout is 0, my_connect() will behave exactly like connect(). @@ -158,17 +164,13 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host, Base version coded by Steve Bernacki, Jr. *****************************************************************************/ -int my_connect(my_socket s, const struct sockaddr *name, uint namelen, +int my_connect(my_socket fd, const struct sockaddr *name, uint namelen, uint timeout) { #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) - return connect(s, (struct sockaddr*) name, namelen); + return connect(fd, (struct sockaddr*) name, namelen); #else int flags, res, s_err; - SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); - fd_set sfds; - struct timeval tv; - time_t start_time, now_time; /* If they passed us a timeout of zero, we should behave @@ -176,30 +178,68 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, */ if (timeout == 0) - return connect(s, (struct sockaddr*) name, namelen); + return connect(fd, (struct sockaddr*) name, namelen); - flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ + flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */ #ifdef O_NONBLOCK - fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ + fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ #endif - res = connect(s, (struct sockaddr*) name, namelen); - s_err = errno; /* Save the error... */ - fcntl(s, F_SETFL, flags); + res= connect(fd, (struct sockaddr*) name, namelen); + s_err= errno; /* Save the error... */ + fcntl(fd, F_SETFL, flags); if ((res != 0) && (s_err != EINPROGRESS)) { - errno = s_err; /* Restore it */ + errno= s_err; /* Restore it */ return(-1); } if (res == 0) /* Connected quickly! */ return(0); + return wait_for_data(fd, timeout); +#endif +} + + +/* + Wait up to timeout seconds for a connection to be established. + + We prefer to do this with poll() as there is no limitations with this. + If not, we will use select() +*/ + +#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__)) + +static int wait_for_data(my_socket fd, uint timeout) +{ +#ifdef HAVE_POLL + struct pollfd ufds; + int res; + + ufds.fd= fd; + ufds.events= POLLIN | POLLPRI; + if (!(res= poll(&ufds, 1, (int) timeout*1000))) + { + errno= EINTR; + return -1; + } + if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI))) + return -1; + return 0; +#else + SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); + fd_set sfds; + struct timeval tv; + time_t start_time, now_time; + int res, s_err; + + if (fd >= FD_SETSIZE) /* Check if wrong error */ + return 0; /* Can't use timeout */ /* - Otherwise, our connection is "in progress." We can use - the select() call to wait up to a specified period of time - for the connection to suceed. If select() returns 0 - (after waiting howevermany seconds), our socket never became - writable (host is probably unreachable.) Otherwise, if + Our connection is "in progress." We can use the select() call to wait + up to a specified period of time for the connection to suceed. + If select() returns 0 (after waiting howevermany seconds), our socket + never became writable (host is probably unreachable.) Otherwise, if select() returns 1, then one of two conditions exist: 1. An error occured. We use getsockopt() to check for this. @@ -212,7 +252,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, */ FD_ZERO(&sfds); - FD_SET(s, &sfds); + FD_SET(fd, &sfds); /* select could be interrupted by a signal, and if it is, the timeout should be adjusted and the select restarted @@ -226,10 +266,10 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, tv.tv_sec = (long) timeout; tv.tv_usec = 0; #if defined(HPUX10) && defined(THREAD) - if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0) + if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0) break; #else - if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0) + if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0) break; #endif if (res == 0) /* timeout */ @@ -247,7 +287,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, */ s_err=0; - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) return(-1); if (s_err) @@ -256,9 +296,9 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, return(-1); /* but return an error... */ } return (0); /* ok */ - -#endif +#endif /* HAVE_POLL */ } +#endif /* defined(__WIN__) || defined(OS2) || defined(__NETWARE__) */ /* Create a named pipe connection From 8bed69fa9ec200925d9a9ec36419d2c5eecf9739 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 17:07:43 +0500 Subject: [PATCH 26/28] Test case for bug #666 mysql-test/r/func_str.result: test for bug #666 result mysql-test/t/func_str.test: test for bug #666 --- mysql-test/r/func_str.result | 13 +++++++++++++ mysql-test/t/func_str.test | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 1a4cb9217e4..09818c14462 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -234,3 +234,16 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); 1 DROP TABLE t1; +CREATE TABLE t1 ( +wid int(10) unsigned NOT NULL auto_increment, +data_podp date default NULL, +status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy', +PRIMARY KEY(wid), +); +INSERT INTO t1 VALUES (8,NULL,'real'); +INSERT INTO t1 VALUES (9,NULL,'nowy'); +SELECT elt(status_wnio,data_podp) FROM t1 GROUP BY wid; +elt(status_wnio,data_podp) +NULL +NULL +DROP TABLE t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 118de6cd01e..476629f98d3 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -125,3 +125,15 @@ CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id ( INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); DROP TABLE t1; + +CREATE TABLE t1 ( + wid int(10) unsigned NOT NULL auto_increment, + data_podp date default NULL, + status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy', + PRIMARY KEY(wid), +); + +INSERT INTO t1 VALUES (8,NULL,'real'); +INSERT INTO t1 VALUES (9,NULL,'nowy'); +SELECT elt(status_wnio,data_podp) FROM t1 GROUP BY wid; +DROP TABLE t1; From 9354da219c43de2286faada566a2ad415a9310ef Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 11:16:06 +0200 Subject: [PATCH 27/28] - reverted change from AC_CONFIG_HEADERS to AM_CONFIG_HEADER in configure.in again - even though the automake docs consider AM_CONFIG_HEADER obsolete, it currently still breaks for too many people to justify this change at the moment. configure.in: - reverted change from AC_CONFIG_HEADERS to AM_CONFIG_HEADER again - even though the automake docs consider AM_CONFIG_HEADER obsolete, it currently still breaks for too many people to justify this change at the moment. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d45aecdf494..a33ccd4a311 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! AM_INIT_AUTOMAKE(mysql, 4.0.14) -AC_CONFIG_HEADERS(config.h) +AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 DOT_FRM_VERSION=6 From 8abad215650386dedf0001812f44859009de74ef Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 17:15:33 +0500 Subject: [PATCH 28/28] Testcase for #674 added mysql-test/r/sel000100.result: Result of the testcase added mysql-test/t/sel000100.test: checking for bug #674 added --- mysql-test/r/sel000100.result | 10 ++++++++++ mysql-test/t/sel000100.test | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/mysql-test/r/sel000100.result b/mysql-test/r/sel000100.result index f9234815a2b..3ffa4004b84 100644 --- a/mysql-test/r/sel000100.result +++ b/mysql-test/r/sel000100.result @@ -26,3 +26,13 @@ ORDER BY link; key_link_id link NULL NULL drop table t1,t2; +CREATE TABLE t1 ( +html varchar(5) default NULL, +rin int(11) default '0', +out int(11) default '0' +) TYPE=MyISAM; +INSERT INTO t1 VALUES ('1',1,0); +SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; +html prod +1 0.00 +drop table t1; diff --git a/mysql-test/t/sel000100.test b/mysql-test/t/sel000100.test index cedb78b17e7..d587fa4ebd0 100644 --- a/mysql-test/t/sel000100.test +++ b/mysql-test/t/sel000100.test @@ -29,3 +29,18 @@ GROUP BY t1.id ORDER BY link; drop table t1,t2; + +# +# test case for #674 +# +CREATE TABLE t1 ( + html varchar(5) default NULL, + rin int(11) default '0', + out int(11) default '0' +) TYPE=MyISAM; + +INSERT INTO t1 VALUES ('1',1,0); + +SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; + +drop table t1;