diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 84f6b60f4d9..e294d969c2f 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -104,6 +104,7 @@ lenz@mysql.com magnus@neptunus.(none) magnus@shellback.(none) marko@hundin.mysql.fi +mats@mysql.com matt@mysql.com matthias@three.local.lan miguel@hegel.(none) diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt index c164e8bd3a0..6370d8aac46 100644 --- a/Docs/mysqld_error.txt +++ b/Docs/mysqld_error.txt @@ -539,8 +539,8 @@ character-set=latin1 "Using storage engine %s for table '%s'", #define ER_CANT_AGGREGATE_2COLLATIONS 1267 "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -#define ER_DROP_USER 1268 -"Can't drop one or more of the requested users", +#define ER_HANDLE_USER 1268 +"Operation %s failed for %d of the requested users", #define ER_REVOKE_GRANTS 1269 "Can't revoke all privileges, grant for one or more of the requested users", #define ER_CANT_AGGREGATE_3COLLATIONS 1270 diff --git a/configure.in b/configure.in index f6dd9c56b20..d3385fc425b 100644 --- a/configure.in +++ b/configure.in @@ -1933,9 +1933,11 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ # # case "$target" in - *-*-aix4*) + *-*-aix4* | *-*-sco*) # (grr) aix 4.3 has a stub for clock_gettime, (returning ENOSYS) # and using AC_TRY_RUN is hard when cross-compiling + # We also disable for SCO for the time being, the headers for the + # thread library we use conflicts with other headers. ;; *) AC_CHECK_FUNCS(clock_gettime) ;; diff --git a/dbug/user.r b/dbug/user.r index 84c5bca908c..f03f0675e0f 100644 --- a/dbug/user.r +++ b/dbug/user.r @@ -907,8 +907,10 @@ Double the colon, if you want it in the path .SP 1 EX: \fCa,C::\\tmp\\log\fR .LI A[,file] -Like 'a[,file]' but close and reopen file after each write. It helps to get -a complete log file in case of crashes. +Like 'a[,file]' but ensure that data are written after each write +(this typically implies flush or close/reopen). It helps to get +a complete log file in case of crashes. This mode is implied in +multi-threaded environment. .LI d[,keywords] Enable output from macros with specified keywords. A null list of keywords implies that all keywords are selected. diff --git a/include/my_sys.h b/include/my_sys.h index 6a20f6aa9dd..3de3ec9687c 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -138,6 +138,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C) #define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C) #define my_strdup_with_length(A,B,C) _my_strdup_with_length((A),(B),__FILE__,__LINE__,C) +#define TRASH(A,B) bfill(A, B, 0x8F) #define QUICK_SAFEMALLOC sf_malloc_quick=1 #define NORMAL_SAFEMALLOC sf_malloc_quick=0 extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick; @@ -164,6 +165,7 @@ extern char *my_strdup_with_length(const byte *from, uint length, #define CALLER_INFO_PROTO /* nothing */ #define CALLER_INFO /* nothing */ #define ORIG_CALLER_INFO /* nothing */ +#define TRASH(A,B) /* nothing */ #endif #ifdef HAVE_ALLOCA diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 478b46dd246..99f126cc23d 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -412,4 +412,5 @@ #define ER_VIEW_MULTIUPDATE 1393 #define ER_VIEW_NO_INSERT_FIELD_LIST 1394 #define ER_VIEW_DELETE_MERGE_VIEW 1395 -#define ER_ERROR_MESSAGES 396 +#define ER_CANNOT_USER 1396 +#define ER_ERROR_MESSAGES 397 diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index d686b559528..2f8ce7507ba 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -548,8 +548,9 @@ buf_pool_init( } /*----------------------------------------*/ } else { - buf_pool->frame_mem = ut_malloc( - UNIV_PAGE_SIZE * (n_frames + 1)); + buf_pool->frame_mem = ut_malloc_low( + UNIV_PAGE_SIZE * (n_frames + 1), + TRUE, FALSE); } if (buf_pool->frame_mem == NULL) { diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 42e3b363ced..985426a9e2b 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -42,6 +42,10 @@ initial segment in buf_LRU_get_recent_limit */ #define BUF_LRU_INITIAL_RATIO 8 +/* If we switch on the InnoDB monitor because there are too few available +frames in the buffer pool, we set this to TRUE */ +ibool buf_lru_switched_on_innodb_mon = FALSE; + /********************************************************************** Takes a block out of the LRU list and page hash table and sets the block state to BUF_BLOCK_REMOVE_HASH. */ @@ -287,6 +291,32 @@ buf_LRU_try_free_flushed_blocks(void) mutex_exit(&(buf_pool->mutex)); } +/********************************************************************** +Returns TRUE if less than 15 % of the buffer pool is available. This can be +used in heuristics to prevent huge transactions eating up the whole buffer +pool for their locks. */ + +ibool +buf_LRU_buf_pool_running_out(void) +/*==============================*/ + /* out: TRUE if less than 15 % of buffer pool + left */ +{ + ibool ret = FALSE; + + mutex_enter(&(buf_pool->mutex)); + + if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) { + + ret = TRUE; + } + + mutex_exit(&(buf_pool->mutex)); + + return(ret); +} + /********************************************************************** Returns a free block from buf_pool. The block is taken off the free list. If it is empty, blocks are moved from the end of the LRU list to the free @@ -325,7 +355,8 @@ loop: } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) { - if (!srv_print_innodb_monitor) { + + if (!buf_lru_switched_on_innodb_mon) { /* Over 80 % of the buffer pool is occupied by lock heaps or the adaptive hash index. This may be a memory @@ -342,16 +373,18 @@ loop: "InnoDB: lock heap and hash index sizes.\n", (ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); + buf_lru_switched_on_innodb_mon = TRUE; srv_print_innodb_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } - } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) - + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) { + } else if (buf_lru_switched_on_innodb_mon) { /* Switch off the InnoDB Monitor; this is a simple way to stop the monitor if the situation becomes less urgent, - but may also surprise users! */ + but may also surprise users if the user also switched on the + monitor! */ + buf_lru_switched_on_innodb_mon = FALSE; srv_print_innodb_monitor = FALSE; } diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h index 69a376f8cab..45164dd561e 100644 --- a/innobase/include/buf0lru.h +++ b/innobase/include/buf0lru.h @@ -25,6 +25,16 @@ wasted. */ void buf_LRU_try_free_flushed_blocks(void); /*==================================*/ +/********************************************************************** +Returns TRUE if less than 15 % of the buffer pool is available. This can be +used in heuristics to prevent huge transactions eating up the whole buffer +pool for their locks. */ + +ibool +buf_LRU_buf_pool_running_out(void); +/*==============================*/ + /* out: TRUE if less than 15 % of buffer pool + left */ /*####################################################################### These are low-level functions diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h index be7667bfd0c..de5ac44e73f 100644 --- a/innobase/include/db0err.h +++ b/innobase/include/db0err.h @@ -53,7 +53,11 @@ Created 5/24/1996 Heikki Tuuri name already exists */ #define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is being dropped right now */ - +#define DB_LOCK_TABLE_FULL 45 /* lock structs have exhausted the + buffer pool (for big transactions, + InnoDB stores the lock structs in the + buffer pool) */ + /* The following are partial failure codes */ #define DB_FAIL 1000 #define DB_OVERFLOW 1001 diff --git a/innobase/include/row0sel.h b/innobase/include/row0sel.h index bb6fb70ca86..8d5187bfc1c 100644 --- a/innobase/include/row0sel.h +++ b/innobase/include/row0sel.h @@ -120,6 +120,7 @@ row_search_for_mysql( /* out: DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, + DB_LOCK_TABLE_FULL, or DB_TOO_BIG_RECORD */ byte* buf, /* in/out: buffer for the fetched row in the MySQL format */ diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h index 73ecb25101a..74357f6bf13 100644 --- a/innobase/include/ut0mem.h +++ b/innobase/include/ut0mem.h @@ -38,8 +38,10 @@ ut_malloc_low( /*==========*/ /* out, own: allocated memory */ ulint n, /* in: number of bytes to allocate */ - ibool set_to_zero); /* in: TRUE if allocated memory should be set + ibool set_to_zero, /* in: TRUE if allocated memory should be set to zero if UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory + cannot be allocated */ /************************************************************************** Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is defined. */ diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c index 023369e8ec5..cb891a03092 100644 --- a/innobase/mem/mem0pool.c +++ b/innobase/mem/mem0pool.c @@ -199,7 +199,7 @@ mem_pool_create( but only when allocated at a higher level in mem0mem.c. This is to avoid masking useful Purify warnings. */ - pool->buf = ut_malloc_low(size, FALSE); + pool->buf = ut_malloc_low(size, FALSE, TRUE); pool->size = size; mutex_create(&(pool->mutex)); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 6ac8c943dc6..0de4b189493 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -308,7 +308,8 @@ handle_new_error: return(TRUE); - } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT) { + } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT + || err == DB_LOCK_TABLE_FULL) { /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 26d26ca323c..27470df81c5 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -730,8 +730,18 @@ sel_set_rec_lock( ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */ que_thr_t* thr) /* in: query thread */ { + trx_t* trx; ulint err; + trx = thr_get_trx(thr); + + if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) { + if (buf_LRU_buf_pool_running_out()) { + + return(DB_LOCK_TABLE_FULL); + } + } + if (index->type & DICT_CLUSTERED) { err = lock_clust_rec_read_check_and_lock(0, rec, index, mode, type, thr); @@ -2790,6 +2800,7 @@ row_search_for_mysql( /* out: DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, + DB_LOCK_TABLE_FULL, or DB_TOO_BIG_RECORD */ byte* buf, /* in/out: buffer for the fetched row in the MySQL format */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 80aea50be2e..ba102b6f4b9 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1783,11 +1783,13 @@ loop: srv_printf_innodb_monitor(stderr); } - mutex_enter(&srv_monitor_file_mutex); - rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file); - os_file_set_eof(srv_monitor_file); - mutex_exit(&srv_monitor_file_mutex); + if (srv_innodb_status) { + mutex_enter(&srv_monitor_file_mutex); + rewind(srv_monitor_file); + srv_printf_innodb_monitor(srv_monitor_file); + os_file_set_eof(srv_monitor_file); + mutex_exit(&srv_monitor_file_mutex); + } if (srv_print_innodb_tablespace_monitor && difftime(current_time, last_table_monitor_time) > 60) { diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 9709f5235de..69341a1d7d1 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1172,6 +1172,9 @@ NetWare. */ } if (ret == NULL) { + fprintf(stderr, +"InnoDB: Fatal error: cannot allocate the memory for the buffer pool\n"); + return(DB_ERROR); } diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index a6002d7fd83..6ed61b0b5de 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -61,8 +61,10 @@ ut_malloc_low( /*==========*/ /* out, own: allocated memory */ ulint n, /* in: number of bytes to allocate */ - ibool set_to_zero) /* in: TRUE if allocated memory should be set + ibool set_to_zero, /* in: TRUE if allocated memory should be set to zero if UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory + cannot be allocated */ { void* ret; @@ -86,9 +88,7 @@ ut_malloc_low( "InnoDB: Check if you should increase the swap file or\n" "InnoDB: ulimits of your operating system.\n" "InnoDB: On FreeBSD check you have compiled the OS with\n" - "InnoDB: a big enough maximum process size.\n" - "InnoDB: We now intentionally generate a seg fault so that\n" - "InnoDB: on Linux we get a stack trace.\n", + "InnoDB: a big enough maximum process size.\n", (ulong) n, (ulong) ut_total_allocated_memory, #ifdef __WIN__ (ulong) GetLastError() @@ -110,7 +110,15 @@ ut_malloc_low( /* Intentional segfault on NetWare causes an abend. Avoid this by graceful exit handling in ut_a(). */ #if (!defined __NETWARE__) - if (*ut_mem_null_ptr) ut_mem_null_ptr = 0; + if (assert_on_error) { + fprintf(stderr, + "InnoDB: We now intentionally generate a seg fault so that\n" + "InnoDB: on Linux we get a stack trace.\n"); + + if (*ut_mem_null_ptr) ut_mem_null_ptr = 0; + } else { + return(NULL); + } #else ut_a(0); #endif @@ -144,7 +152,7 @@ ut_malloc( /* out, own: allocated memory */ ulint n) /* in: number of bytes to allocate */ { - return(ut_malloc_low(n, TRUE)); + return(ut_malloc_low(n, TRUE, TRUE)); } /************************************************************************** diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result index 56676abba33..c515ee9a1e8 100644 --- a/mysql-test/r/ansi.result +++ b/mysql-test/r/ansi.result @@ -2,7 +2,7 @@ drop table if exists t1; set sql_mode="MySQL40"; select @@sql_mode; @@sql_mode -NO_FIELD_OPTIONS,MYSQL40,BROKEN_NOT +NO_FIELD_OPTIONS,MYSQL40,HIGH_NOT_PRECEDENCE set @@sql_mode="ANSI"; select @@sql_mode; @@sql_mode diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result index 1ef4b55fc36..184046a2d6f 100644 --- a/mysql-test/r/bool.result +++ b/mysql-test/r/bool.result @@ -33,7 +33,7 @@ a SELECT * FROM t1 where (1 AND a) IS NULL; a NULL -set sql_mode='broken_not'; +set sql_mode='high_not_precedence'; select * from t1 where not a between 2 and 3; a set sql_mode=default; diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index 11dbcca9431..9bc8e417e19 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -69,6 +69,6 @@ Error 1259 ZLIB: Input data corrupted Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted) drop table t1; set @@max_allowed_packet=1048576*100; -select compress(repeat('aaaaaaaaaa', 10000000)) is null; -compress(repeat('aaaaaaaaaa', 10000000)) is null +select compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null; +compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null 0 diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 1ac6165e383..31903a5dfd2 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -218,17 +218,19 @@ grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; -ERROR HY000: Can't drop one or more of the requested users revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost' drop table t1; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' +GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost' drop user mysqltest_1@localhost; SET NAMES koi8r; CREATE DATABASE ÂÄ; @@ -252,6 +254,7 @@ Grants for GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost' GRANT SELECT (ËÏÌ) ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost' REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁ FROM ÀÚÅÒ@localhost; +DROP USER ÀÚÅÒ@localhost; DROP DATABASE ÂÄ; SET NAMES latin1; USE test; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 9e1e5d50f31..edfd1a07680 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -60,3 +60,165 @@ use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; +set sql_mode='maxdb'; +drop table if exists t1, t2; +create table t1(c1 int); +create table t2(c1 int, c2 int); +create user 'mysqltest_1'; +create user 'mysqltest_1'; +ERROR HY000: Operation CREATE USER failed for 'mysqltest_1'@'%' +create user 'mysqltest_2' identified by 'Mysqltest-2'; +create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +grant select on *.* to 'mysqltest_2'; +grant insert on test.* to 'mysqltest_2'; +grant update on test.t1 to 'mysqltest_2'; +grant update (c2) on test.t2 to 'mysqltest_2'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_1 +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_2 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_2 t1 +% test mysqltest_2 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_2 t2 c2 +show grants for 'mysqltest_1'; +Grants for mysqltest_1@% +GRANT USAGE ON *.* TO 'mysqltest_1'@'%' +show grants for 'mysqltest_2'; +Grants for mysqltest_2@% +GRANT SELECT ON *.* TO 'mysqltest_2'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1' +GRANT INSERT ON "test".* TO 'mysqltest_2'@'%' +GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_2'@'%' +GRANT UPDATE ON "test"."t1" TO 'mysqltest_2'@'%' +drop user 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_2 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_2 t1 +% test mysqltest_2 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_2 t2 c2 +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +rename user 'mysqltest_2' to 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_1 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_1 t1 +% test mysqltest_1 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_1 t2 c2 +show grants for 'mysqltest_1'; +Grants for mysqltest_1@% +GRANT SELECT ON *.* TO 'mysqltest_1'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1' +GRANT INSERT ON "test".* TO 'mysqltest_1'@'%' +GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%' +GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%' +drop user 'mysqltest_1', 'mysqltest_3'; +grant all on test.t1 to 'mysqltest_1'; +ERROR 42000: 'root'@'localhost' is not allowed to create new users +drop user 'mysqltest_1'; +ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%' +drop table t1, t2; +insert into mysql.db set user='mysqltest_1', db='%', host='%'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +revoke all privileges, grant option from 'mysqltest_1'; +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users +drop user 'mysqltest_1'; +select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +host db user +insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +drop user 'mysqltest_1'; +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +host db user table_name +insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +drop user 'mysqltest_1'; +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +host db user table_name column_name +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%','mysqltest_2'@'%','mysqltest_3'@'%' +drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a'; +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a'; +ERROR HY000: Operation CREATE USER failed for 'mysqltest_2'@'%' +rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b'; +ERROR HY000: Operation RENAME USER failed for 'mysqltest_2a'@'%' +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b'; +ERROR HY000: Operation DROP USER failed for 'mysqltest_2b'@'%' +create user 'mysqltest_2' identified by 'Mysqltest-2'; +drop user 'mysqltest_2' identified by 'Mysqltest-2'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'Mysqltest-2'' at line 1 +create user '%@b'@'b'; +show grants for '%@b'@'b'; +Grants for %@b@b +GRANT USAGE ON *.* TO '%@b'@'b' +grant select on mysql.* to '%@b'@'b'; +show grants for '%@b'@'b'; +Grants for %@b@b +GRANT USAGE ON *.* TO '%@b'@'b' +GRANT SELECT ON "mysql".* TO '%@b'@'b' +rename user '%@b'@'b' to '%@a'@'a'; +show grants for '%@b'@'b'; +ERROR 42000: There is no such grant defined for user '%@b' on host 'b' +show grants for '%@a'@'a'; +Grants for %@a@a +GRANT USAGE ON *.* TO '%@a'@'a' +GRANT SELECT ON "mysql".* TO '%@a'@'a' +drop user '%@a'@'a'; +create user mysqltest_2@localhost; +grant usage on *.* to mysqltest_2@localhost with grant option; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysql' +create user mysqltest_A@'%'; +rename user mysqltest_A@'%' to mysqltest_B@'%'; +drop user mysqltest_B@'%'; +drop user mysqltest_2@localhost; +create user mysqltest_3@localhost; +grant all privileges on mysql.* to mysqltest_3@localhost; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +localhost mysqltest_3 +insert into mysql.user set host='%', user='mysqltest_B'; +create user mysqltest_A@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +rename user mysqltest_B@'%' to mysqltest_C@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +drop user mysqltest_B@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +drop user mysqltest_B@'%'; +drop user mysqltest_3@localhost; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 8f5ac88b7d0..cba78422253 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -252,7 +252,7 @@ sel2 sel2 select count(*) from information_schema.ROUTINES; count(*) 2 -create view v0 (c) as select schema_name from information_schema.SCHEMATA; +create view v0 (c) as select schema_name from information_schema.schemata; select * from v0; c mysql @@ -260,22 +260,22 @@ test explain select * from v0; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY # ALL NULL NULL NULL NULL 2 -create view v1 (c) as select table_name from information_schema.TABLES +create view v1 (c) as select table_name from information_schema.tables where table_name="v1"; select * from v1; c v1 -create view v2 (c) as select column_name from information_schema.COLUMNS +create view v2 (c) as select column_name from information_schema.columns where table_name="v2"; select * from v2; c c -create view v3 (c) as select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS +create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets where CHARACTER_SET_NAME like "latin1%"; select * from v3; c latin1 -create view v4 (c) as select COLLATION_NAME from information_schema.COLLATIONS +create view v4 (c) as select COLLATION_NAME from information_schema.collations where COLLATION_NAME like "latin1%"; select * from v4; c @@ -289,13 +289,13 @@ latin1_general_cs latin1_spanish_ci show keys from v4; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -select * from information_schema.VIEWS where TABLE_NAME like "v%"; +select * from information_schema.views where TABLE_NAME like "v%"; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE -NULL test v0 select `SCHEMATA`.`SCHEMA_NAME` AS `c` from `information_schema`.`SCHEMATA` NONE NO -NULL test v1 select `TABLES`.`TABLE_NAME` AS `c` from `information_schema`.`TABLES` where (`TABLES`.`TABLE_NAME` = _utf8'v1') NONE NO -NULL test v2 select `COLUMNS`.`COLUMN_NAME` AS `c` from `information_schema`.`COLUMNS` where (`COLUMNS`.`TABLE_NAME` = _utf8'v2') NONE NO -NULL test v3 select `CHARACTER_SETS`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`CHARACTER_SETS` where (`CHARACTER_SETS`.`CHARACTER_SET_NAME` like _utf8'latin1%') NONE NO -NULL test v4 select `COLLATIONS`.`COLLATION_NAME` AS `c` from `information_schema`.`COLLATIONS` where (`COLLATIONS`.`COLLATION_NAME` like _utf8'latin1%') NONE NO +NULL test v0 select `schemata`.`SCHEMA_NAME` AS `c` from `information_schema`.`schemata` NONE NO +NULL test v1 select `tables`.`TABLE_NAME` AS `c` from `information_schema`.`tables` where (`tables`.`TABLE_NAME` = _utf8'v1') NONE NO +NULL test v2 select `columns`.`COLUMN_NAME` AS `c` from `information_schema`.`columns` where (`columns`.`TABLE_NAME` = _utf8'v2') NONE NO +NULL test v3 select `character_sets`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`character_sets` where (`character_sets`.`CHARACTER_SET_NAME` like _utf8'latin1%') NONE NO +NULL test v4 select `collations`.`COLLATION_NAME` AS `c` from `information_schema`.`collations` where (`collations`.`COLLATION_NAME` like _utf8'latin1%') NONE NO drop view v0, v1, v2, v3, v4; create table t1 (a int); grant select,update,insert on t1 to mysqltest_1@localhost; @@ -434,18 +434,18 @@ information_schema.tables; s1 9 drop table t1; -SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; Table Create Table -CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` ( +character_sets CREATE TEMPORARY TABLE `character_sets` ( `CHARACTER_SET_NAME` char(30) NOT NULL default '', `DESCRIPTION` char(60) NOT NULL default '', `DEFAULT_COLLATE_NAME` char(60) NOT NULL default '', `MAXLEN` bigint(3) NOT NULL default '0' ) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2282 set names latin2; -SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; Table Create Table -CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` ( +character_sets CREATE TEMPORARY TABLE `character_sets` ( `CHARACTER_SET_NAME` char(30) NOT NULL default '', `DESCRIPTION` char(60) NOT NULL default '', `DEFAULT_COLLATE_NAME` char(60) NOT NULL default '', @@ -517,3 +517,19 @@ from information_schema.columns; open c; open c; end;// call p108()// ERROR 24000: Cursor is already open drop procedure p108; +create view v1 as select A1.table_name from information_schema.TABLES A1 +where table_name= "user"; +select * from v1; +table_name +user +drop view v1; +create view vo as select 'a' union select 'a'; +show index from vo; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +select * from information_schema.TABLE_CONSTRAINTS where +TABLE_NAME= "vo"; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_METHOD +select * from information_schema.KEY_COLUMN_USAGE where +TABLE_NAME= "vo"; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME +drop view vo; diff --git a/mysql-test/r/ndb_grant.result b/mysql-test/r/ndb_grant.result index 6583065a0c4..6192a7cace5 100644 --- a/mysql-test/r/ndb_grant.result +++ b/mysql-test/r/ndb_grant.result @@ -31,8 +31,8 @@ begin; grant delete on mysqltest.* to mysqltest_1@localhost; commit; select * from mysql.user where user="mysqltest_1"; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections -localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections +localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 0 0 0 show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA' @@ -99,7 +99,7 @@ commit; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION begin; revoke all privileges on mysqltest.* from mysqltest_1@localhost; commit; @@ -271,23 +271,26 @@ grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; commit; +flush privileges; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; -ERROR HY000: Can't drop one or more of the requested users begin; revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users commit; +flush privileges; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop table t1; begin; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; commit; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' +GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost' drop user mysqltest_1@localhost; SET NAMES koi8r; CREATE DATABASE ÂÄ; @@ -396,6 +399,31 @@ DROP DATABASE testdb7; DROP DATABASE testdb8; DROP DATABASE testdb9; DROP DATABASE testdb10; +SHOW PRIVILEGES; +Privilege Context Comment +Alter Tables To alter the table +Create Databases,Tables,Indexes To create new databases and tables +Create temporary tables Databases To use CREATE TEMPORARY TABLE +Create view Tables To create new views +Delete Tables To delete existing rows +Drop Databases,Tables To drop databases, tables, and views +File File access on server To read and write files on the server +Grant option Databases,Tables To give to other users those privileges you possess +Index Tables To create or drop indexes +Insert Tables To insert data into tables +Lock tables Databases To use LOCK TABLES (together with SELECT privilege) +Process Server Admin To view the plain text of currently executing queries +References Databases,Tables To have references on tables +Reload Server Admin To reload or refresh tables, logs and privileges +Replication client Server Admin To ask where the slave or master servers are +Replication slave Server Admin To read binary log events from the master +Select Tables To retrieve rows from table +Show databases Server Admin To see all databases with SHOW DATABASES +Show view Tables To see views with SHOW CREATE VIEW +Shutdown Server Admin To shut down the server +Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc. +Update Tables To update existing rows +Usage Server Admin No privileges - allow connect only use mysql; alter table columns_priv engine=myisam; alter table db engine=myisam; diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 15643f29513..abc48783cf4 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -733,3 +733,10 @@ xxxxxxxxxxxxxxxxxxxaa xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxz drop table t1; +create table t1 (a int not null, b int not null, c int not null); +insert t1 values (1,1,1),(1,1,2),(1,2,1); +select a, b from t1 group by a, b order by sum(c); +a b +1 2 +1 1 +drop table t1; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index e8d8e4063f1..9b12b0baa1d 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -835,19 +835,19 @@ identified by 'looser' ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' drop table mysqltest.t9 ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' prepare s_t1 from 'select a as my_col from t1' ; execute s_t1 ; my_col diff --git a/mysql-test/r/rpl_start_stop_slave.result b/mysql-test/r/rpl_start_stop_slave.result new file mode 100644 index 00000000000..1fcb586d1fb --- /dev/null +++ b/mysql-test/r/rpl_start_stop_slave.result @@ -0,0 +1,12 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +stop slave; +create table t1(n int); +start slave; +stop slave io_thread; +start slave io_thread; +drop table t1; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ffc7c176a48..72b46374e66 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2321,6 +2321,27 @@ select * from t2,t3 where t2.s = t3.s; s s two two drop table t1, t2, t3; +create table t1 (a integer, b integer, index(a), index(b)); +create table t2 (c integer, d integer, index(c), index(d)); +insert into t1 values (1,2), (2,2), (3,2), (4,2); +insert into t2 values (1,3), (2,3), (3,4), (4,4); +explain select * from t1 left join t2 on a=c where d in (4); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref c,d d 5 const 2 Using where +1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where +select * from t1 left join t2 on a=c where d in (4); +a b c d +3 2 3 4 +4 2 4 4 +explain select * from t1 left join t2 on a=c where d = 4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref c,d d 5 const 2 Using where +1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where +select * from t1 left join t2 on a=c where d = 4; +a b c d +3 2 3 4 +4 2 4 4 +drop table t1, t2; CREATE TABLE t1 ( i int(11) NOT NULL default '0', c char(10) NOT NULL default '', @@ -2333,9 +2354,6 @@ INSERT INTO t1 VALUES (3,'c'); EXPLAIN SELECT i FROM t1 WHERE i=1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index -EXPLAIN SELECT i FROM t1 WHERE i=1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index DROP TABLE t1; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 9bea0fe0d4c..642f1aedd78 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -460,4 +460,17 @@ end| call bug3294()| ERROR 42S02: Unknown table 't5' drop procedure bug3294| +drop procedure if exists bug6807| +create procedure bug6807() +begin +declare id int; +set id = connection_id(); +kill query id; +select 'Not reached'; +end| +call bug6807()| +ERROR 70100: Query execution was interrupted +call bug6807()| +ERROR 70100: Query execution was interrupted +drop procedure bug6807| drop table t1| diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index c25ae99b530..fea99086303 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` ( set @@sql_mode="no_field_options,mysql323,mysql40"; show variables like 'sql_mode'; Variable_name Value -sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,BROKEN_NOT +sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,HIGH_NOT_PRECEDENCE show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 19c4def9b32..b7c5ac38b76 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -713,8 +713,8 @@ NULL -99.99 DROP TABLE t1; CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED); -INSERT INTO t1 VALUES (-1.1E-38,0),(+3.4E+38,+3.4E+38); -INSERT INTO t1 VALUES ('-1.1E-38',0),('+3.4E+38','+3.4E+38'); +INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38); +INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38'); INSERT INTO t1 (col1) VALUES (3E-46); INSERT INTO t1 (col1) VALUES (+3.4E+39); ERROR 22003: Out of range value adjusted for column 'col1' at row 1 @@ -752,9 +752,9 @@ Warning 1264 Out of range value adjusted for column 'col1' at row 1 Warning 1264 Out of range value adjusted for column 'col2' at row 1 SELECT * FROM t1; col1 col2 --1.1e-38 0 +-1.1e-37 0 3.4e+38 3.4e+38 --1.1e-38 0 +-1.1e-37 0 3.4e+38 3.4e+38 0 NULL 2 NULL @@ -763,8 +763,8 @@ NULL NULL 3.40282e+38 0 DROP TABLE t1; CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED); -INSERT INTO t1 VALUES (-2.2E-308,0),(+1.7E+308,+1.7E+308); -INSERT INTO t1 VALUES ('-2.2E-308',0),('+1.7E+308','+1.7E+308'); +INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308); +INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308'); INSERT INTO t1 (col1) VALUES (-2.2E-330); INSERT INTO t1 (col1) VALUES (+1.7E+309); ERROR 22007: Illegal double '1.7E+309' value found during parsing @@ -801,9 +801,9 @@ Warning 1264 Out of range value adjusted for column 'col2' at row 1 Warning 1264 Out of range value adjusted for column 'col2' at row 1 SELECT * FROM t1; col1 col2 --2.2e-308 0 +-2.2e-307 0 1.7e+308 1.7e+308 --2.2e-308 0 +-2.2e-307 0 1.7e+308 1.7e+308 0 NULL 2 NULL diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index e2c6b3f2ae2..f4430ae1004 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -8,7 +8,7 @@ create temporary table t1 (a int, b int); create view v1 (c) as select b+1 from t1; ERROR HY000: View's SELECT contains a temporary table 't1' drop table t1; -create table t1 (a int, b int); +create table t1 (a int, b int) max_rows=1000000; insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); create view v1 (c,d) as select a,b+@@global.max_user_connections from t1; ERROR HY000: View's SELECT contains a variable or parameter @@ -149,7 +149,7 @@ v5 VIEW v6 VIEW show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 9 Fixed 5 9 45 150994943 1024 0 NULL # # NULL latin1_swedish_ci NULL max_rows=1000000 v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view @@ -1213,18 +1213,14 @@ select * from v1; drop view v1; drop table t1; create function x1 () returns int return 5; -create table t1 (s1 int); +create table t1 (s1 int) max_rows=1000000; create view v1 as select x1() from t1; drop function x1; select * from v1; ERROR 42000: FUNCTION test.x1 does not exist show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL -v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL FUNCTION test.x1 does not exist -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 9 Fixed 0 0 0 83886079 1024 0 NULL # # NULL latin1_swedish_ci NULL max_rows=1000000 v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL FUNCTION test.x1 does not exist drop view v1; drop table t1; diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test index 644fdbfbf60..53230dd5fa3 100644 --- a/mysql-test/t/bool.test +++ b/mysql-test/t/bool.test @@ -21,7 +21,7 @@ SELECT * FROM t1 where (1 AND a)=1; SELECT * FROM t1 where (1 AND a) IS NULL; # WL#638 - Behaviour of NOT does not follow SQL specification -set sql_mode='broken_not'; +set sql_mode='high_not_precedence'; select * from t1 where not a between 2 and 3; set sql_mode=default; select * from t1 where not a between 2 and 3; diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 7b70289d2c0..f46589e9e0e 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -38,7 +38,10 @@ drop table t1; # # Bug #5497: a problem with large strings +# note that when LOW_MEMORY is set the "test" below is meaningless # set @@max_allowed_packet=1048576*100; -select compress(repeat('aaaaaaaaaa', 10000000)) is null; +--replace_result "''" XXX "'1'" XXX +eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null; + diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index dfd5f4db7c6..eda08ac0cdb 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -162,16 +162,18 @@ grant select(a) on test.t1 to drop_user1@localhost; grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; ---error 1268 +# Drop user now implicitly revokes all privileges. drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +--error 1269 revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +--error 1396 drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop table t1; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; show grants for mysqltest_1@localhost; drop user mysqltest_1@localhost; @@ -195,6 +197,9 @@ GRANT SELECT ( SHOW GRANTS FOR ÀÚÅÒ@localhost; REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁ FROM ÀÚÅÒ@localhost; +# Revoke does not drop user. Leave a clean user table for the next tests. +DROP USER ÀÚÅÒ@localhost; + DROP DATABASE ÂÄ; SET NAMES latin1; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index fe4a5b55b82..69c42ce2252 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -78,3 +78,152 @@ use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; + +# +# Create and drop user +# +set sql_mode='maxdb'; +--disable_warnings +drop table if exists t1, t2; +--enable_warnings +create table t1(c1 int); +create table t2(c1 int, c2 int); +# +# Three forms of CREATE USER +create user 'mysqltest_1'; +--error 1396 +create user 'mysqltest_1'; +create user 'mysqltest_2' identified by 'Mysqltest-2'; +create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +grant select on *.* to 'mysqltest_2'; +grant insert on test.* to 'mysqltest_2'; +grant update on test.t1 to 'mysqltest_2'; +grant update (c2) on test.t2 to 'mysqltest_2'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +show grants for 'mysqltest_1'; +show grants for 'mysqltest_2'; +# +# Drop +drop user 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +--error 1141 +show grants for 'mysqltest_1'; +# +# Rename +rename user 'mysqltest_2' to 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +show grants for 'mysqltest_1'; +drop user 'mysqltest_1', 'mysqltest_3'; +# +# Grant must not create user +--error 1211 +grant all on test.t1 to 'mysqltest_1'; +--error 1396 +drop user 'mysqltest_1'; +# +# Cleanup +drop table t1, t2; +# +# Add a stray record +insert into mysql.db set user='mysqltest_1', db='%', host='%'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +--error 1269 +revoke all privileges, grant option from 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +# +# Add a stray record +insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +# +# Add a stray record +insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +# +# Handle multi user lists +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a'; +--error 1396 +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a'; +# +# Let one of multiple users fail +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +--error 1396 +create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a'; +--error 1396 +rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +--error 1396 +drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b'; +# +# Obsolete syntax has been dropped +create user 'mysqltest_2' identified by 'Mysqltest-2'; +--error 1064 +drop user 'mysqltest_2' identified by 'Mysqltest-2'; +# +# Strange user names +create user '%@b'@'b'; +show grants for '%@b'@'b'; +grant select on mysql.* to '%@b'@'b'; +show grants for '%@b'@'b'; +rename user '%@b'@'b' to '%@a'@'a'; +--error 1141 +show grants for '%@b'@'b'; +show grants for '%@a'@'a'; +drop user '%@a'@'a'; +# +# USAGE WITH GRANT OPTION is sufficient. +create user mysqltest_2@localhost; +grant usage on *.* to mysqltest_2@localhost with grant option; +connect (user2,localhost,mysqltest_2,,); +connection user2; +--error 1044 +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +create user mysqltest_A@'%'; +rename user mysqltest_A@'%' to mysqltest_B@'%'; +drop user mysqltest_B@'%'; +disconnect user2; +connection default; +drop user mysqltest_2@localhost; +# +# ALL PRIVILEGES without GRANT OPTION is not sufficient. +create user mysqltest_3@localhost; +grant all privileges on mysql.* to mysqltest_3@localhost; +connect (user3,localhost,mysqltest_3,,); +connection user3; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +insert into mysql.user set host='%', user='mysqltest_B'; +--error 1044 +create user mysqltest_A@'%'; +--error 1044 +rename user mysqltest_B@'%' to mysqltest_C@'%'; +--error 1044 +drop user mysqltest_B@'%'; +disconnect user3; +connection default; +drop user mysqltest_B@'%'; +drop user mysqltest_3@localhost; +# + diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 411301445a3..93e201c5121 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -110,24 +110,24 @@ select count(*) from information_schema.ROUTINES; # # Test for views # -create view v0 (c) as select schema_name from information_schema.SCHEMATA; +create view v0 (c) as select schema_name from information_schema.schemata; select * from v0; --replace_column 3 # explain select * from v0; -create view v1 (c) as select table_name from information_schema.TABLES +create view v1 (c) as select table_name from information_schema.tables where table_name="v1"; select * from v1; -create view v2 (c) as select column_name from information_schema.COLUMNS +create view v2 (c) as select column_name from information_schema.columns where table_name="v2"; select * from v2; -create view v3 (c) as select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS +create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets where CHARACTER_SET_NAME like "latin1%"; select * from v3; -create view v4 (c) as select COLLATION_NAME from information_schema.COLLATIONS +create view v4 (c) as select COLLATION_NAME from information_schema.collations where COLLATION_NAME like "latin1%"; select * from v4; show keys from v4; -select * from information_schema.VIEWS where TABLE_NAME like "v%"; +select * from information_schema.views where TABLE_NAME like "v%"; drop view v0, v1, v2, v3, v4; # @@ -222,9 +222,9 @@ information_schema.tables) union select version from information_schema.tables; drop table t1; -SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; set names latin2; -SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; set names latin1; create table t1 select * from information_schema.CHARACTER_SETS @@ -260,3 +260,16 @@ from information_schema.columns; open c; open c; end;// call p108()// delimiter ;// drop procedure p108; + +create view v1 as select A1.table_name from information_schema.TABLES A1 +where table_name= "user"; +select * from v1; +drop view v1; + +create view vo as select 'a' union select 'a'; +show index from vo; +select * from information_schema.TABLE_CONSTRAINTS where +TABLE_NAME= "vo"; +select * from information_schema.KEY_COLUMN_USAGE where +TABLE_NAME= "vo"; +drop view vo; diff --git a/mysql-test/t/ndb_grant.test b/mysql-test/t/ndb_grant.test index d3899d9972f..b4885d2c5fc 100644 --- a/mysql-test/t/ndb_grant.test +++ b/mysql-test/t/ndb_grant.test @@ -226,19 +226,23 @@ grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; commit; ---error 1268 +flush privileges; +# Drop user now implicitly revokes all privileges. drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; begin; +--error 1269 revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; commit; +flush privileges; +#--error 1268 drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop table t1; begin; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; commit; show grants for mysqltest_1@localhost; drop user mysqltest_1@localhost; @@ -351,6 +355,11 @@ DROP DATABASE testdb8; DROP DATABASE testdb9; DROP DATABASE testdb10; +# +# just SHOW PRIVILEGES test +# +SHOW PRIVILEGES; + # # Alter mysql system tables back to myisam # diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 988c106bf21..dd36cd95969 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -500,3 +500,9 @@ insert into t1 set a = concat(repeat('x', 19), 'aa'); set max_sort_length=20; select a from t1 order by a; drop table t1; + +create table t1 (a int not null, b int not null, c int not null); +insert t1 values (1,1,1),(1,1,2),(1,2,1); +select a, b from t1 group by a, b order by sum(c); +drop table t1; + diff --git a/mysql-test/t/rpl_start_stop_slave.test b/mysql-test/t/rpl_start_stop_slave.test new file mode 100644 index 00000000000..903ff204194 --- /dev/null +++ b/mysql-test/t/rpl_start_stop_slave.test @@ -0,0 +1,34 @@ +source include/master-slave.inc; + +# +# Bug#6148 () +# +connection slave; +stop slave; + +# Let the master do lots of insertions +connection master; +create table t1(n int); +let $1=5000; +disable_query_log; +while ($1) +{ + eval insert into t1 values($1); + dec $1; +} +enable_query_log; +save_master_pos; + +connection slave; +start slave; +sleep 1; +stop slave io_thread; +start slave io_thread; +sync_with_master; + +connection master; +drop table t1; +save_master_pos; + +connection slave; +sync_with_master; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 3a3c1243c7c..e548aba29fe 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1899,6 +1899,20 @@ select * from t1,t2 where t1.s = t2.s; select * from t2,t3 where t2.s = t3.s; drop table t1, t2, t3; +# +# Bug #3759 +# Both queries should produce identical plans and results. +# +create table t1 (a integer, b integer, index(a), index(b)); +create table t2 (c integer, d integer, index(c), index(d)); +insert into t1 values (1,2), (2,2), (3,2), (4,2); +insert into t2 values (1,3), (2,3), (3,4), (4,4); +explain select * from t1 left join t2 on a=c where d in (4); +select * from t1 left join t2 on a=c where d in (4); +explain select * from t1 left join t2 on a=c where d = 4; +select * from t1 left join t2 on a=c where d = 4; +drop table t1, t2; + # # Covering index is mentioned in EXPLAIN output for const tables (bug #5333) # @@ -1916,8 +1930,6 @@ INSERT INTO t1 VALUES (3,'c'); EXPLAIN SELECT i FROM t1 WHERE i=1; -EXPLAIN SELECT i FROM t1 WHERE i=1; - DROP TABLE t1; # diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index c04f8e6f9e9..c24f9df16be 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -632,6 +632,28 @@ end| call bug3294()| drop procedure bug3294| +# +# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY +# +--disable_warnings +drop procedure if exists bug6807| +--enable_warnings +create procedure bug6807() +begin + declare id int; + + set id = connection_id(); + kill query id; + select 'Not reached'; +end| + +--error 1317 +call bug6807()| +--error 1317 +call bug6807()| + +drop procedure bug6807| + drop table t1| diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index d9f4f4f2d0c..4f7c0cfc541 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -493,8 +493,8 @@ DROP TABLE t1; # Test INSERT with FLOAT CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED); -INSERT INTO t1 VALUES (-1.1E-38,0),(+3.4E+38,+3.4E+38); -INSERT INTO t1 VALUES ('-1.1E-38',0),('+3.4E+38','+3.4E+38'); +INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38); +INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38'); # We don't give warnings for underflow INSERT INTO t1 (col1) VALUES (3E-46); --error 1264 @@ -527,8 +527,8 @@ DROP TABLE t1; # Test INSERT with DOUBLE CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED); -INSERT INTO t1 VALUES (-2.2E-308,0),(+1.7E+308,+1.7E+308); -INSERT INTO t1 VALUES ('-2.2E-308',0),('+1.7E+308','+1.7E+308'); +INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308); +INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308'); # We don't give warnings for underflow INSERT INTO t1 (col1) VALUES (-2.2E-330); --error 1367 diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 92747323336..5b2eeaca966 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -9,20 +9,20 @@ use test; # some basic test of views and its functionality # -# create view on unexistence table +# create view on nonexistent table -- error 1146 create view v1 (c,d) as select a,b from t1; create temporary table t1 (a int, b int); -#view on temporary table +# view on temporary table -- error 1352 create view v1 (c) as select b+1 from t1; drop table t1; -create table t1 (a int, b int); +create table t1 (a int, b int) max_rows=1000000; insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); -#view with variable +# view with variable -- error 1351 create view v1 (c,d) as select a,b+@@global.max_user_connections from t1; @@ -30,7 +30,7 @@ create view v1 (c,d) as select a,b+@@global.max_user_connections from t1; create view v1 (c) as select b+1 from t1; select c from v1; -#tamporary table should not shade (hide) table of view +# temporary table should not hide table of view create temporary table t1 (a int, b int); # this is empty select * from t1; @@ -42,7 +42,7 @@ show create view v1; show create view t1; drop table t1; -# try to use fields from underlaid table +# try to use fields from underlying table -- error 1054 select a from v1; -- error 1054 @@ -52,14 +52,14 @@ select b from v1; -- error 1054 select v1.b from v1; -# view with different algorithms (explain out put are differ) +# view with different algorithms (explain output differs) explain extended select c from v1; create algorithm=temptable view v2 (c) as select b+1 from t1; show create view v2; select c from v2; explain extended select c from v2; -# try to use underlaid table fields in VIEW creation process +# try to use underlying table fields in VIEW creation process -- error 1054 create view v3 (c) as select a+1 from v1; -- error 1054 @@ -127,19 +127,19 @@ show grants for test@localhost; revoke create view on test.* from test@localhost; show grants for test@localhost; -#try to drop unexisten VIEW +# try to drop nonexistent VIEW -- error 1051 drop view v100; -#try to drop table with DROP VIEW +# try to drop table with DROP VIEW -- error 1347 drop view t1; -#try to drop VIEW with DROP TABLE +# try to drop VIEW with DROP TABLE -- error 1051 drop table v1; -#try to drop table with DROP VIEW +# try to drop table with DROP VIEW drop view v1,v2; drop table t1; @@ -213,7 +213,7 @@ grant select (c) on mysqltest.v1 to mysqltest_1@localhost; connection user1; select c from mysqltest.v1; -# there are not privilege ob column 'd' +# there are no privileges on column 'd' -- error 1143 select d from mysqltest.v1; @@ -233,7 +233,7 @@ grant select (c) on mysqltest.v1 to mysqltest_1@localhost; connection user1; select c from mysqltest.v1; -# there are not privilege ob column 'd' +# there are no privileges on column 'd' -- error 1143 select d from mysqltest.v1; @@ -288,7 +288,7 @@ explain select c from mysqltest.v4; -- error 1142 show create view mysqltest.v4; -# allow to see one of underlaing table +# allow to see one of underlying table connection root; grant select on mysqltest.t1 to mysqltest_1@localhost; connection user1; @@ -328,7 +328,7 @@ delete from mysql.user where user='mysqltest_1'; drop database mysqltest; # -# QUERY CHECHE options for VIEWs +# QUERY CACHE options for VIEWs # set GLOBAL query_cache_size=1355776; flush status; @@ -425,7 +425,7 @@ drop table t1; drop view v1,v2; # -# LIMIT clasuse test +# LIMIT clause test # create table t1 (a int); insert into t1 values (1), (2), (3), (4); @@ -538,7 +538,7 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; drop database mysqltest; # -# MEREGE VIEW with WHERE clause +# MERGE VIEW with WHERE clause # create table t1 (a int, b int, primary key(b)); insert into t1 values (1,20), (2,30), (3,40), (4,50), (5,100); @@ -811,7 +811,7 @@ create view mysqltest.v1 as select * from mysqltest.t1; -- error 1143 create view v3 as select a from mysqltest.t2; -# give CRETEA VIEW privileges (without any privileges for result colemn) +# give CREATE VIEW privileges (without any privileges for result column) connection root; create table mysqltest.v3 (b int); grant create view on mysqltest.v3 to mysqltest_1@localhost; @@ -826,7 +826,7 @@ drop view mysqltest.v3; connection user1; create view mysqltest.v3 as select b from mysqltest.t2; -# give UPDATE and INSERT privilege (to get more privileges then anderlying +# give UPDATE and INSERT privilege (to get more privileges then underlying # table) connection root; grant create view, update, insert on mysqltest.v3 to mysqltest_1@localhost; @@ -836,8 +836,8 @@ connection user1; create view mysqltest.v3 as select b from mysqltest.t2; -# If give other privileges for VIEW then underlaying table have => -# creation prohibited +# If we would get more privileges on VIEW then we have on +# underlying tables => creation prohibited connection root; create table mysqltest.v3 (b int); grant select(b) on mysqltest.v3 to mysqltest_1@localhost; @@ -897,7 +897,7 @@ drop view v1; drop table `t1a``b`; # -# Changing of underlaying table +# Changing of underlying table # create table t1 (col1 char(5),col2 char(5)); create view v1 as select * from t1; @@ -927,7 +927,7 @@ call p1(); drop procedure p1; # -# updateablity should be transitive +# updatablity should be transitive # create table t1 (col1 int,col2 char(22)); insert into t1 values(5,'Hello, world of views'); @@ -960,7 +960,7 @@ drop view v1; drop table t1; # -# Test of view updatebility in prepared statement +# Test of view updatability in prepared statement # create table t1 (a int); create view v1 as select a from t1; @@ -1162,23 +1162,21 @@ drop view v1; drop table t1; # -# VIEW over droped function +# VIEW over dropped function # create function x1 () returns int return 5; -create table t1 (s1 int); +create table t1 (s1 int) max_rows=1000000; create view v1 as select x1() from t1; drop function x1; -- error 1305 select * from v1; --replace_column 12 # 13 # show table status; ---replace_column 12 # 13 # -show table status; drop view v1; drop table t1; # -# VIEW with floating point (long bumber) as column +# VIEW with floating point (long number) as column # create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1; show create view v1; @@ -1213,7 +1211,7 @@ select * from v1; drop view v1; # -# bug handlimg from VIEWs +# bug handling from VIEWs # create view v1 as select 'a',1; create view v2 as select * from v1 union all select * from v1; diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index 5a551b3dd97..1bd90f9d8ec 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -127,14 +127,23 @@ protected: NdbReceiver** m_receivers; // All receivers Uint32* m_prepared_receivers; // These are to be sent - + + /** + * owned by API/user thread + */ Uint32 m_current_api_receiver; Uint32 m_api_receivers_count; NdbReceiver** m_api_receivers; // These are currently used by api + /** + * owned by receiver thread + */ Uint32 m_conf_receivers_count; // NOTE needs mutex to access NdbReceiver** m_conf_receivers; // receive thread puts them here + /** + * owned by receiver thread + */ Uint32 m_sent_receivers_count; // NOTE needs mutex to access NdbReceiver** m_sent_receivers; // receive thread puts them here diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index ca3a2a2186d..831d14eac52 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -379,18 +379,30 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, "Unable to connect with connect string: %s", cfg.makeConnectString(buf,sizeof(buf))); + if (verbose == -2) + ndbout << ", failed." << endl; return -1; } if (verbose == -1) { - ndbout << "retrying every " << retry_delay_in_seconds << " seconds:"; + ndbout << "Retrying every " << retry_delay_in_seconds << " seconds"; + if (no_retries > 0) + ndbout << ". Attempts left:"; + else + ndbout << ", until connected.";; + ndbout << flush; verbose= -2; } - NdbSleep_SecSleep(retry_delay_in_seconds); - if (verbose == -2) { - ndbout << " " << no_retries; + if (no_retries > 0) { + if (verbose == -2) { + ndbout << " " << no_retries; + ndbout << flush; + } + no_retries--; } - no_retries--; + NdbSleep_SecSleep(retry_delay_in_seconds); } + if (verbose == -2) + ndbout << endl; handle->cfg_i = i; diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 54beaa49d3f..bfe8b6786b4 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -44,7 +44,7 @@ public: * Constructor * @param mgmtSrvr: Management server to use when executing commands */ - CommandInterpreter(const char *); + CommandInterpreter(const char *, int verbose); ~CommandInterpreter(); /** @@ -94,6 +94,7 @@ private: */ void executeHelp(char* parameters); void executeShow(char* parameters); + void executeConnect(char* parameters); void executePurge(char* parameters); void executeShutdown(char* parameters); void executeRun(char* parameters); @@ -153,6 +154,7 @@ private: NdbMgmHandle m_mgmsrv; bool connected; + int m_verbose; int try_reconnect; #ifdef HAVE_GLOBAL_REPLICATION NdbRepHandle m_repserver; @@ -169,9 +171,9 @@ private: #include "ndb_mgmclient.hpp" #include "ndb_mgmclient.h" -Ndb_mgmclient::Ndb_mgmclient(const char *host) +Ndb_mgmclient::Ndb_mgmclient(const char *host,int verbose) { - m_cmd= new CommandInterpreter(host); + m_cmd= new CommandInterpreter(host,verbose); } Ndb_mgmclient::~Ndb_mgmclient() { @@ -275,6 +277,7 @@ static const char* helpText = "REP CONNECT Connect to REP server on host:port\n" #endif "PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server\n" +"CONNECT Connect to management server (reconnect if already connected)\n" "QUIT Quit management client\n" ; @@ -373,7 +376,8 @@ convert(const char* s, int& val) { /* * Constructor */ -CommandInterpreter::CommandInterpreter(const char *_host) +CommandInterpreter::CommandInterpreter(const char *_host,int verbose) + : m_verbose(verbose) { m_mgmsrv = ndb_mgm_create_handle(); if(m_mgmsrv == NULL) { @@ -437,7 +441,15 @@ CommandInterpreter::connect() { if(!connected) { if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) + { connected = true; + if (m_verbose) + { + printf("Connected to Management Server at: %s:%d\n", + ndb_mgm_get_connected_host(m_mgmsrv), + ndb_mgm_get_connected_port(m_mgmsrv)); + } + } } return connected; } @@ -445,7 +457,7 @@ CommandInterpreter::connect() bool CommandInterpreter::disconnect() { - if (ndb_mgm_disconnect(m_mgmsrv) == -1) { + if (connected && (ndb_mgm_disconnect(m_mgmsrv) == -1)) { ndbout_c("Could not disconnect from management server"); printError(); } @@ -459,18 +471,21 @@ CommandInterpreter::disconnect() int CommandInterpreter::execute(const char *_line, int _try_reconnect) { + DBUG_ENTER("CommandInterpreter::execute"); + DBUG_PRINT("info",("line=\"%s\"",_line)); + if (_try_reconnect >= 0) try_reconnect=_try_reconnect; char * line; if(_line == NULL) { // ndbout << endl; - return false; + DBUG_RETURN(false); } line = my_strdup(_line,MYF(MY_WME)); My_auto_ptr ptr(line); if (emptyString(line)) { - return true; + DBUG_RETURN(true); } for (unsigned int i = 0; i < strlen(line); ++i) { @@ -484,41 +499,49 @@ CommandInterpreter::execute(const char *_line, int _try_reconnect) if (strcmp(firstToken, "HELP") == 0 || strcmp(firstToken, "?") == 0) { executeHelp(allAfterFirstToken); - return true; + DBUG_RETURN(true); } - else if (strcmp(firstToken, "SHOW") == 0) { + else if (strcmp(firstToken, "CONNECT") == 0) { + executeConnect(allAfterFirstToken); + DBUG_RETURN(true); + } + + if (!connect()) + DBUG_RETURN(true); + + if (strcmp(firstToken, "SHOW") == 0) { executeShow(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if (strcmp(firstToken, "SHUTDOWN") == 0) { executeShutdown(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if (strcmp(firstToken, "CLUSTERLOG") == 0){ executeClusterLog(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if(strcmp(firstToken, "START") == 0 && allAfterFirstToken != NULL && strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){ executeStartBackup(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if(strcmp(firstToken, "ABORT") == 0 && allAfterFirstToken != NULL && strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){ executeAbortBackup(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if (strcmp(firstToken, "PURGE") == 0) { executePurge(allAfterFirstToken); - return true; + DBUG_RETURN(true); } #ifdef HAVE_GLOBAL_REPLICATION else if(strcmp(firstToken, "REPLICATION") == 0 || strcmp(firstToken, "REP") == 0) { executeRep(allAfterFirstToken); - return true; + DBUG_RETURN(true); } #endif // HAVE_GLOBAL_REPLICATION else if(strcmp(firstToken, "ENTER") == 0 && @@ -526,14 +549,14 @@ CommandInterpreter::execute(const char *_line, int _try_reconnect) strncmp(allAfterFirstToken, "SINGLE USER MODE ", sizeof("SINGLE USER MODE") - 1) == 0){ executeEnterSingleUser(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if(strcmp(firstToken, "EXIT") == 0 && allAfterFirstToken != NULL && strncmp(allAfterFirstToken, "SINGLE USER MODE ", sizeof("SINGLE USER MODE") - 1) == 0){ executeExitSingleUser(allAfterFirstToken); - return true; + DBUG_RETURN(true); } else if (strcmp(firstToken, "ALL") == 0) { analyseAfterFirstToken(-1, allAfterFirstToken); @@ -542,7 +565,7 @@ CommandInterpreter::execute(const char *_line, int _try_reconnect) strcmp(firstToken, "EXIT") == 0 || strcmp(firstToken, "BYE") == 0) && allAfterFirstToken == NULL){ - return false; + DBUG_RETURN(false); } else { /** * First token should be a digit, node ID @@ -552,18 +575,18 @@ CommandInterpreter::execute(const char *_line, int _try_reconnect) if (! convert(firstToken, nodeId)) { ndbout << "Invalid command: " << line << endl; ndbout << "Type HELP for help." << endl << endl; - return true; + DBUG_RETURN(true); } if (nodeId < 0) { ndbout << "Invalid node ID: " << firstToken << "." << endl; - return true; + DBUG_RETURN(true); } analyseAfterFirstToken(nodeId, allAfterFirstToken); } - return true; + DBUG_RETURN(true); } @@ -692,7 +715,6 @@ CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, ndbout_c("Trying to start all nodes of system."); ndbout_c("Use ALL STATUS to see the system start-up phases."); } else { - connect(); struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(m_mgmsrv); if(cl == 0){ ndbout_c("Unable get status from management server"); @@ -826,8 +848,6 @@ CommandInterpreter::executeHelp(char* parameters) void CommandInterpreter::executeShutdown(char* parameters) { - connect(); - ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv); if(state == NULL) { ndbout_c("Could not get status"); @@ -979,7 +999,6 @@ CommandInterpreter::executePurge(char* parameters) int i; char *str; - connect(); if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) { ndbout_c("Command failed"); @@ -999,7 +1018,6 @@ void CommandInterpreter::executeShow(char* parameters) { int i; - connect(); if (emptyString(parameters)) { ndbout << "Cluster Configuration" << endl << "---------------------" << endl; @@ -1087,6 +1105,12 @@ CommandInterpreter::executeShow(char* parameters) } } +void +CommandInterpreter::executeConnect(char* parameters) +{ + disconnect(); + connect(); +} //***************************************************************************** //***************************************************************************** @@ -1094,7 +1118,6 @@ void CommandInterpreter::executeClusterLog(char* parameters) { int i; - connect(); if (parameters != 0 && strlen(parameters) != 0) { enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL; int isOk = true; @@ -1240,7 +1263,6 @@ CommandInterpreter::executeClusterLog(char* parameters) void CommandInterpreter::executeStop(int processId, const char *, bool all) { - connect(); int result = 0; if(all) { result = ndb_mgm_stop(m_mgmsrv, 0, 0); @@ -1262,7 +1284,6 @@ CommandInterpreter::executeStop(int processId, const char *, bool all) void CommandInterpreter::executeEnterSingleUser(char* parameters) { - connect(); strtok(parameters, " "); struct ndb_mgm_reply reply; char* id = strtok(NULL, " "); @@ -1289,7 +1310,6 @@ CommandInterpreter::executeEnterSingleUser(char* parameters) void CommandInterpreter::executeExitSingleUser(char* parameters) { - connect(); int result = ndb_mgm_exit_single_user(m_mgmsrv, 0); if (result != 0) { ndbout_c("Exiting single user mode failed."); @@ -1304,7 +1324,6 @@ void CommandInterpreter::executeStart(int processId, const char* parameters, bool all) { - connect(); int result; if(all) { result = ndb_mgm_start(m_mgmsrv, 0, 0); @@ -1328,7 +1347,6 @@ void CommandInterpreter::executeRestart(int processId, const char* parameters, bool all) { - connect(); int result; int nostart = 0; int initialstart = 0; @@ -1378,7 +1396,6 @@ CommandInterpreter::executeDumpState(int processId, const char* parameters, ndbout << "Expected argument" << endl; return; } - connect(); Uint32 no = 0; int pars[25]; @@ -1418,7 +1435,6 @@ CommandInterpreter::executeStatus(int processId, return; } - connect(); ndb_mgm_node_status status; Uint32 startPhase, version; bool system; @@ -1469,7 +1485,6 @@ void CommandInterpreter::executeLogLevel(int processId, const char* parameters, bool all) { - connect(); (void) all; BaseString tmp(parameters); @@ -1525,7 +1540,6 @@ void CommandInterpreter::executeError(int processId, return; } - connect(); // Copy parameters since strtok will modify it char* newpar = my_strdup(parameters,MYF(MY_WME)); My_auto_ptr ap1(newpar); @@ -1589,7 +1603,6 @@ void CommandInterpreter::executeLog(int processId, const char* parameters, bool all) { - connect(); struct ndb_mgm_reply reply; Vector blocks; if (! parseBlockSpecification(parameters, blocks)) { @@ -1657,7 +1670,6 @@ CommandInterpreter::executeTestOn(int processId, ndbout << "No parameters expected to this command." << endl; return; } - connect(); struct ndb_mgm_reply reply; int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply); if (result != 0) { @@ -1676,7 +1688,6 @@ CommandInterpreter::executeTestOff(int processId, ndbout << "No parameters expected to this command." << endl; return; } - connect(); struct ndb_mgm_reply reply; int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply); if (result != 0) { @@ -1798,8 +1809,6 @@ CommandInterpreter::executeEventReporting(int processId, ndbout << "Expected argument" << endl; return; } - connect(); - BaseString tmp(parameters); Vector spec; tmp.split(spec, "="); @@ -1850,7 +1859,6 @@ CommandInterpreter::executeEventReporting(int processId, void CommandInterpreter::executeStartBackup(char* /*parameters*/) { - connect(); struct ndb_mgm_reply reply; unsigned int backupId; @@ -1897,8 +1905,6 @@ CommandInterpreter::executeStartBackup(char* /*parameters*/) void CommandInterpreter::executeAbortBackup(char* parameters) { - connect(); - strtok(parameters, " "); struct ndb_mgm_reply reply; char* id = strtok(NULL, "\0"); @@ -1952,7 +1958,6 @@ CommandInterpreter::executeRep(char* parameters) return; } - connect(); char * line = my_strdup(parameters,MYF(MY_WME)); My_auto_ptr ap1((char*)line); char * firstToken = strtok(line, " "); diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp index f32cc683296..08d5d60cfab 100644 --- a/ndb/src/mgmclient/main.cpp +++ b/ndb/src/mgmclient/main.cpp @@ -56,17 +56,18 @@ handler(int sig){ } } - +static const char default_prompt[]= "ndb_mgm> "; static unsigned _try_reconnect; static char *opt_connect_str= 0; +static const char *prompt= default_prompt; static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_mgm"), { "try-reconnect", 't', - "Specify number of retries for connecting to ndb_mgmd, default infinite", + "Specify number of tries for connecting to ndb_mgmd (0 = infinite)", (gptr*) &_try_reconnect, (gptr*) &_try_reconnect, 0, - GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + GET_UINT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; static void short_usage_sub(void) @@ -116,13 +117,13 @@ read_and_execute(int _try_reconnect) } #ifdef HAVE_READLINE /* Get a line from the user. */ - line_read = readline ("ndb_mgm> "); + line_read = readline (prompt); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) add_history (line_read); #else static char linebuffer[254]; - fputs("ndb_mgm> ", stdout); + fputs(prompt, stdout); linebuffer[sizeof(linebuffer)-1]=0; line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin); if (line_read == linebuffer) { @@ -155,12 +156,16 @@ int main(int argc, char** argv){ opt_connect_str= buf; } + if (!isatty(0)) + { + prompt= 0; + } + ndbout << "-- NDB Cluster -- Management Client --" << endl; - printf("Connecting to Management Server: %s\n", opt_connect_str ? opt_connect_str : "default"); signal(SIGPIPE, handler); - com = new Ndb_mgmclient(opt_connect_str); + com = new Ndb_mgmclient(opt_connect_str,1); while(read_and_execute(_try_reconnect)); delete com; diff --git a/ndb/src/mgmclient/ndb_mgmclient.hpp b/ndb/src/mgmclient/ndb_mgmclient.hpp index f6bcebc3896..ea592dfdf4e 100644 --- a/ndb/src/mgmclient/ndb_mgmclient.hpp +++ b/ndb/src/mgmclient/ndb_mgmclient.hpp @@ -21,7 +21,7 @@ class CommandInterpreter; class Ndb_mgmclient { public: - Ndb_mgmclient(const char*); + Ndb_mgmclient(const char*,int verbose=0); ~Ndb_mgmclient(); int execute(const char *_line, int _try_reconnect=-1); int execute(int argc, char** argv, int _try_reconnect=-1); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 81b5eb9dfb3..986da71a8e8 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -432,15 +432,20 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server, theFacade = 0; m_newConfig = NULL; - m_configFilename.assign(config_filename); + if (config_filename) + m_configFilename.assign(config_filename); + else + m_configFilename.assign("config.ini"); m_nextConfigGenerationNumber = 0; m_config_retriever= new ConfigRetriever(connect_string, NDB_VERSION, NDB_MGM_NODE_TYPE_MGM); - + // if connect_string explicitly given or + // no config filename is given then // first try to allocate nodeid from another management server - if(m_config_retriever->do_connect(0,0,0) == 0) + if ((connect_string || config_filename == NULL) && + (m_config_retriever->do_connect(0,0,0) == 0)) { int tmp_nodeid= 0; tmp_nodeid= m_config_retriever->allocNodeId(0 /*retry*/,0 /*delay*/); diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index 84ff98626e5..64a2cb35c1f 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -176,7 +176,6 @@ int main(int argc, char** argv) #endif global_mgmt_server_check = 1; - glob.config_filename= "config.ini"; const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; load_defaults("my",load_default_groups,&argc,&argv); diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbConnectionScan.cpp index a1a220caacf..b0c546c512a 100644 --- a/ndb/src/ndbapi/NdbConnectionScan.cpp +++ b/ndb/src/ndbapi/NdbConnectionScan.cpp @@ -56,7 +56,7 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){ const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr()); if(checkState_TransId(&ref->transId1)){ - theScanningOp->theError.code = ref->errorCode; + theScanningOp->setErrorCode(ref->errorCode); theScanningOp->execCLOSE_SCAN_REP(); if(!ref->closeNeeded){ return 0; diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 832ca7da275..7acc64093e8 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -278,9 +278,9 @@ NdbScanOperation::fix_receivers(Uint32 parallel){ void NdbScanOperation::receiver_delivered(NdbReceiver* tRec){ if(theError.code == 0){ - if(DEBUG_NEXT_RESULT) - ndbout_c("receiver_delivered"); - + if(DEBUG_NEXT_RESULT) + ndbout_c("receiver_delivered"); + Uint32 idx = tRec->m_list_index; Uint32 last = m_sent_receivers_count - 1; if(idx != last){ @@ -441,6 +441,9 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend) Uint32 nodeId = theNdbCon->theDBnode; TransporterFacade* tp = TransporterFacade::instance(); Guard guard(tp->theMutexPtr); + if(theError.code) + return -1; + Uint32 seq = theNdbCon->theNodeSequence; if(seq == tp->getNodeSequence(nodeId) && send_next_scan(idx, false, forceSend) == 0){ @@ -646,10 +649,8 @@ void NdbScanOperation::closeScan(bool forceSend) void NdbScanOperation::execCLOSE_SCAN_REP(){ - m_api_receivers_count = 0; m_conf_receivers_count = 0; m_sent_receivers_count = 0; - m_current_api_receiver = m_ordered ? theParallelism : 0; } void NdbScanOperation::release() @@ -1314,6 +1315,8 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, if(DEBUG_NEXT_RESULT) ndbout_c("performing fetch..."); TransporterFacade* tp = TransporterFacade::instance(); Guard guard(tp->theMutexPtr); + if(theError.code) + return -1; Uint32 seq = theNdbCon->theNodeSequence; Uint32 nodeId = theNdbCon->theDBnode; if(seq == tp->getNodeSequence(nodeId) && @@ -1328,6 +1331,13 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, continue; } if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); + setErrorCode(4028); + return -1; + } + + if(theError.code){ + setErrorCode(theError.code); + if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); return -1; } @@ -1337,11 +1347,9 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, memcpy(arr, m_conf_receivers, u_last * sizeof(char*)); if(DEBUG_NEXT_RESULT) ndbout_c("sent: %d recv: %d", tmp, u_last); - if(theError.code){ - setErrorCode(theError.code); - if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); - return -1; - } + } else { + setErrorCode(4028); + return -1; } } else { if(DEBUG_NEXT_RESULT) ndbout_c("return 2"); @@ -1481,6 +1489,13 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ } } + if(theError.code) + { + m_api_receivers_count = 0; + m_current_api_receiver = m_ordered ? theParallelism : 0; + } + + /** * move all conf'ed into api * so that send_next_scan can check if they needs to be closed diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index bc49358cc63..6744f4c1640 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -241,11 +241,12 @@ ErrorBundle ErrorCodes[] = { { 877, AE, "877" }, { 878, AE, "878" }, { 879, AE, "879" }, + { 880, AE, "Tried to read too much - too many getValue calls" }, { 884, AE, "Stack overflow in interpreter" }, { 885, AE, "Stack underflow in interpreter" }, { 886, AE, "More than 65535 instructions executed in interpreter" }, + { 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" }, { 4256, AE, "Must call Ndb::init() before this function" }, - { 880, AE, "Tried to read too much - too many getValue calls" }, { 4257, AE, "Tried to read too much - too many getValue calls" }, /** diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp index 51913e8fbf9..22ec3fff327 100644 --- a/ndb/test/ndbapi/testScan.cpp +++ b/ndb/test/ndbapi/testScan.cpp @@ -90,11 +90,59 @@ int runLoadAllTables(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +char orderedPkIdxName[255]; + +int createOrderedPkIndex(NDBT_Context* ctx, NDBT_Step* step){ + + const NdbDictionary::Table* pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + // Create index + BaseString::snprintf(orderedPkIdxName, sizeof(orderedPkIdxName), + "IDC_O_PK_%s", pTab->getName()); + NdbDictionary::Index pIdx(orderedPkIdxName); + pIdx.setTable(pTab->getName()); + pIdx.setType(NdbDictionary::Index::OrderedIndex); + pIdx.setLogging(false); + + for (int c = 0; c< pTab->getNoOfColumns(); c++){ + const NdbDictionary::Column * col = pTab->getColumn(c); + if(col->getPrimaryKey()){ + pIdx.addIndexColumn(col->getName()); + } + } + + if (pNdb->getDictionary()->createIndex(pIdx) != 0){ + ndbout << "FAILED! to create index" << endl; + const NdbError err = pNdb->getDictionary()->getNdbError(); + ERR(err); + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int createOrderedPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){ + const NdbDictionary::Table* pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + // Drop index + if (pNdb->getDictionary()->dropIndex(orderedPkIdxName, + pTab->getName()) != 0){ + ndbout << "FAILED! to drop index" << endl; + ERR(pNdb->getDictionary()->getNdbError()); + return NDBT_FAILED; + } + + return NDBT_OK; +} + + int runScanReadRandomTable(NDBT_Context* ctx, NDBT_Step* step){ int loops = ctx->getNumLoops(); int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 240); - int abort = ctx->getProperty("AbortProb"); + int abort = ctx->getProperty("AbortProb", 5); int i = 0; while (igetNumLoops(); int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 240); - int abort = ctx->getProperty("AbortProb"); + int abort = ctx->getProperty("AbortProb", 5); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); @@ -232,11 +280,58 @@ int runScanRead(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runRandScanRead(NDBT_Context* ctx, NDBT_Step* step){ + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + int parallelism = ctx->getProperty("Parallelism", 240); + int abort = ctx->getProperty("AbortProb", 5); + + int i = 0; + HugoTransactions hugoTrans(*ctx->getTab()); + while (iisTestStopped()) { + g_info << i << ": "; + NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3); + if (hugoTrans.scanReadRecords(GETNDB(step), + records, abort, parallelism, + lm) != 0){ + return NDBT_FAILED; + } + i++; + } + return NDBT_OK; +} + +int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){ + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + int parallelism = ctx->getProperty("Parallelism", 240); + int abort = ctx->getProperty("AbortProb", 5); + const NdbDictionary::Index * pIdx = + GETNDB(step)->getDictionary()->getIndex(orderedPkIdxName, + ctx->getTab()->getName()); + + int i = 0; + HugoTransactions hugoTrans(*ctx->getTab()); + while (pIdx && iisTestStopped()) { + g_info << i << ": "; + bool sort = (rand() % 100) > 50 ? true : false; + NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3); + if (hugoTrans.scanReadRecords(GETNDB(step), pIdx, + records, abort, parallelism, + lm, + sort) != 0){ + return NDBT_FAILED; + } + i++; + } + return NDBT_OK; +} + int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){ int loops = ctx->getNumLoops(); int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 240); - int abort = ctx->getProperty("AbortProb"); + int abort = ctx->getProperty("AbortProb", 5); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); @@ -425,7 +520,7 @@ int runScanUpdate(NDBT_Context* ctx, NDBT_Step* step){ int loops = ctx->getNumLoops(); int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 1); - int abort = ctx->getProperty("AbortProb"); + int abort = ctx->getProperty("AbortProb", 5); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); while (igetNumLoops(); int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 240); - int abort = ctx->getProperty("AbortProb"); + int abort = ctx->getProperty("AbortProb", 5); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); while (iused_tables(); - not_null_tables_cache&= row->not_null_tables(); + not_null_tables_cache= row->not_null_tables(); with_sum_func= with_sum_func || row->with_sum_func; const_item_cache&= row->const_item(); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 01866a786a6..eb3db156056 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3543,7 +3543,7 @@ Item_func_sp::execute(Item **itp) m_sp= sp_find_function(thd, m_name); if (! m_sp) { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname); + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); DBUG_RETURN(-1); } @@ -3577,7 +3577,7 @@ Item_func_sp::field_type() const DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns)); DBUG_RETURN(m_sp->m_returns); } - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname); + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); DBUG_RETURN(MYSQL_TYPE_STRING); } @@ -3593,7 +3593,7 @@ Item_func_sp::result_type() const { DBUG_RETURN(m_sp->result()); } - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname); + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); DBUG_RETURN(STRING_RESULT); } @@ -3606,7 +3606,7 @@ Item_func_sp::fix_length_and_dec() m_sp= sp_find_function(current_thd, m_name); if (! m_sp) { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname); + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); } else { diff --git a/sql/item_func.h b/sql/item_func.h index 03df78d721d..241240a49ca 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1035,11 +1035,7 @@ public: table->file->ft_handler=0; table->fulltext_searched=0; } - if (concat) - { - delete concat; - concat= 0; - } + concat= 0; DBUG_VOID_RETURN; } enum Functype functype() const { return FT_FUNC; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index eb53394b96b..babb0c1aa6f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -282,7 +282,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2) #define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2) #define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2) -#define MODE_BROKEN_NOT (MODE_NO_AUTO_CREATE_USER*2) +#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2) #define RAID_BLOCK_SIZE 1024 @@ -809,8 +809,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator *it, bool any_privileges, - bool allocate_view_names, - bool select_insert); + bool allocate_view_names); bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, TABLE_LIST **leaves, bool refresh_only, bool select_insert); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 48b60cc6824..5a97daa04ae 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -221,7 +221,7 @@ const char *sql_mode_names[] = "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", - "TRADITIONAL", "NO_AUTO_CREATE_USER", "BROKEN_NOT", + "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", NullS }; TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 6392a2fee32..e92d266ba28 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1360,7 +1360,7 @@ public: /* Table read plans are allocated on MEM_ROOT and are never deleted */ static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) {} + static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } }; class TRP_ROR_INTERSECT; @@ -2716,7 +2716,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, double min_cost= read_time; DBUG_ENTER("get_best_ror_intersect"); - if (tree->n_ror_scans < 2) + if ((tree->n_ror_scans < 2) || !param->table->file->records) DBUG_RETURN(NULL); /* @@ -2803,6 +2803,9 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, min_cost= intersect->total_cost; best_rows= (ha_rows)(intersect->records_fract* rows2double(param->table->file->records)); + /* Prevent divisons by zero */ + if (!best_rows) + best_rows= 1; is_best_covering= intersect->is_covering; intersect_scans_best= intersect_scans_end; best_index_scan_costs= intersect->index_scan_costs; @@ -2847,6 +2850,9 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, min_cost= intersect->total_cost; best_rows= (ha_rows)(intersect->records_fract* rows2double(param->table->file->records)); + /* Prevent divisons by zero */ + if (!best_rows) + best_rows= 1; is_best_covering= intersect->is_covering; best_index_scan_costs= intersect->index_scan_costs; } @@ -2866,7 +2872,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, trp->last_scan= trp->first_scan + best_num; trp->is_covering= is_best_covering; trp->read_cost= min_cost; - trp->records= best_rows? best_rows : 1; + trp->records= best_rows; trp->index_scan_costs= best_index_scan_costs; trp->cpk_scan= cpk_scan; DBUG_PRINT("info", diff --git a/sql/protocol.cc b/sql/protocol.cc index 88be2710422..11a915ec151 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -131,36 +131,6 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_VOID_RETURN; } - -/* - Send a warning to the end user - - SYNOPSIS - send_warning() - thd Thread handler - sql_errno Warning number (error message) - err Error string. If not set, use ER(sql_errno) - - DESCRIPTION - Register the warning so that the user can get it with mysql_warnings() - Send an ok (+ warning count) to the end user. -*/ - -void send_warning(THD *thd, uint sql_errno, const char *err) -{ - DBUG_ENTER("send_warning"); - if (thd->spcont && - thd->spcont->find_handler(sql_errno, MYSQL_ERROR::WARN_LEVEL_WARN)) - { - DBUG_VOID_RETURN; - } - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno, - err ? err : ER(sql_errno)); - send_ok(thd); - DBUG_VOID_RETURN; -} - - /* Write error package and flush to client It's a little too low level, but I don't want to use another buffer for diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 5f67143065b..f759be59ffb 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -917,8 +917,8 @@ bool load_master_data(THD* thd) */ int error; - if (init_master_info(active_mi, master_info_file, relay_log_info_file, - 0)) + if (init_master_info(active_mi, master_info_file, relay_log_info_file, + 0, (SLAVE_IO | SLAVE_SQL))) my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); strmake(active_mi->master_log_name, row[0], sizeof(active_mi->master_log_name)); diff --git a/sql/set_var.cc b/sql/set_var.cc index 46865de9314..532547c2618 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3146,9 +3146,9 @@ ulong fix_sql_mode(ulong sql_mode) MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); if (sql_mode & MODE_MYSQL40) - sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT; + sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE; if (sql_mode & MODE_MYSQL323) - sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT; + sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE; if (sql_mode & MODE_TRADITIONAL) sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 55a8499145a..e8ea55f0739 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -296,7 +296,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -424,3 +424,4 @@ character-set=latin2 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index ee1341cf095..3664e5ba0ef 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -287,7 +287,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -415,3 +415,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 26ff759ca40..cd71ddc3588 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -296,7 +296,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -424,3 +424,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 8abb684fe11..3050f94936f 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for %.256s", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 1211bd305dd..58b032ceb14 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin7 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -417,3 +417,4 @@ character-set=latin7 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 5c54b5e01a8..a93a52606a9 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 4d1a4a17ebe..e657f9cb16a 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -425,3 +425,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Das Kommando %s scheiterte für %.256s", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 146d25cfaee..0bfcf513001 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -284,7 +284,7 @@ character-set=greek "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=greek "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index be195b86503..51338770817 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -417,3 +417,4 @@ character-set=latin2 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 685d2d0c972..f7f553c0eca 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 665e1991198..694447caa48 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -288,7 +288,7 @@ character-set=ujis "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -416,3 +416,4 @@ character-set=ujis "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index d4f59b768ff..3916b10666d 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -284,7 +284,7 @@ character-set=euckr "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=euckr "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 780bfd8d8ca..8165dc142fe 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -414,3 +414,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index d723d0cc475..477c527968a 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -414,3 +414,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index b3242c46310..5c56730068d 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -417,3 +417,4 @@ character-set=latin2 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index b2a993bf002..2ccde22a78f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Dado truncado para coluna '%s' na linha %ld", "Usando engine de armazenamento %s para tabela '%s'", "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'", -"Não pode remover um ou mais dos usuários pedidos", +"Cannot drop one or more of the requested users", "Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos", "Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'", "Ilegal combinação de collations para operação '%s'", @@ -414,3 +414,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 7f5ef856d3a..2b2f6aa45a8 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -417,3 +417,4 @@ character-set=latin2 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 74cafac8b52..58301983b25 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -289,7 +289,7 @@ character-set=koi8r "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -417,3 +417,4 @@ character-set=koi8r "îÅÌØÚÑ ÉÚÍÅÎÉÔØ ÂÏÌØÛÅ ÞÅÍ ÏÄÎÕ ÂÁÚÏ×ÕÀ ÔÁÂÌÉÃÕ ÉÓÐÏÌØÚÕÑ ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s'" "îÅÌØÚÑ ×ÓÔÁ×ÌÑÔØ ÚÁÐÉÓÉ × ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s' ÂÅÚ ÓÐÉÓËÁ ÐÏÌÅÊ" "îÅÌØÚÑ ÕÄÁÌÑÔØ ÉÚ ÍÎÏÇÏÔÁÂÌÉÞÎÏÇÏ VIEW '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 9a09358a35a..a245da6b677 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -277,7 +277,7 @@ character-set=cp1250 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -405,3 +405,4 @@ character-set=cp1250 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 4c694fecc88..69eddcfa9f6 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -292,7 +292,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -420,3 +420,4 @@ character-set=latin2 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 94316edd083..0eefed18088 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -288,7 +288,7 @@ character-set=latin1 "Datos truncados para columna '%s' en la línea %ld", "Usando motor de almacenamiento %s para tabla '%s'", "Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'", -"No puede remover uno o mas de los usuarios solicitados", +"Cannot drop one or more of the requested users", "No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados", "Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'", "Ilegal mezcla de collations para operación '%s'", @@ -416,3 +416,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index cd57653969f..be42d3889d0 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Använder handler %s för tabell '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -412,3 +412,4 @@ character-set=latin1 "Can not modify more than one base table through a join view '%-.64s.%-.64s'" "Can not insert into join view '%-.64s.%-.64s' without fields list" "Can not delete from join view '%-.64s.%-.64s'" +"Operation %s failed for '%.256s'", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 0b3400a4e88..6d4c37803c7 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -290,7 +290,7 @@ character-set=koi8u "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Cannot drop one or more of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", @@ -418,3 +418,4 @@ character-set=koi8u "îÅÍÏÖÌÉ×Ï ÏÎÏ×ÉÔÉ Â¦ÌØÛ ÎÉÖ ÏÄÎÕ ÂÁÚÏ×Õ ÔÁÂÌÉÃÀ ×ÙËÏÒÉÓÔÏ×ÕÀÞÉ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔ¦ÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ" "îÅÍÏÖÌÉ×Ï ÕÓÔÁ×ÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ, ÂÅÚ ÓÐÉÓËÕ ÓÔÏ×Âæ×" "îÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ" +"Operation %s failed for '%.256s'", diff --git a/sql/slave.cc b/sql/slave.cc index 04ab4830312..e67def552bd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -160,7 +160,7 @@ int init_slave() } if (init_master_info(active_mi,master_info_file,relay_log_info_file, - !master_host)) + !master_host, (SLAVE_IO | SLAVE_SQL))) { sql_print_error("Failed to initialize the master info structure"); goto err; @@ -1981,7 +1981,8 @@ void clear_until_condition(RELAY_LOG_INFO* rli) int init_master_info(MASTER_INFO* mi, const char* master_info_fname, const char* slave_info_fname, - bool abort_if_no_master_info_file) + bool abort_if_no_master_info_file, + int thread_mask) { int fd,error; char fname[FN_REFLEN+128]; @@ -1995,8 +1996,16 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname, last time. If this case pos_in_file would be set and we would get a crash when trying to read the signature for the binary relay log. + + We only rewind the read position if we are starting the SQL + thread. The handle_slave_sql thread assumes that the read + position is at the beginning of the file, and will read the + "signature" and then fast-forward to the last position read. */ - my_b_seek(mi->rli.cur_log, (my_off_t) 0); + if (thread_mask & SLAVE_SQL) + { + my_b_seek(mi->rli.cur_log, (my_off_t) 0); + } DBUG_RETURN(0); } diff --git a/sql/slave.h b/sql/slave.h index e73c81a1e6f..1abe166c944 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -520,7 +520,8 @@ void clear_until_condition(RELAY_LOG_INFO* rli); void clear_slave_error_timestamp(RELAY_LOG_INFO* rli); int init_master_info(MASTER_INFO* mi, const char* master_info_fname, const char* slave_info_fname, - bool abort_if_no_master_info_file); + bool abort_if_no_master_info_file, + int thread_mask); void end_master_info(MASTER_INFO* mi); int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname); void end_relay_log_info(RELAY_LOG_INFO* rli); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9ce00a01e31..0c6b061aa0c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -919,7 +919,7 @@ static void acl_update_user(const char *user, const char *host, { if (!acl_user->host.hostname && !host[0] || acl_user->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_user->host.hostname)) { acl_user->access=privileges; if (mqh->bits & 1) @@ -998,7 +998,7 @@ static void acl_update_db(const char *user, const char *host, const char *db, { if (!acl_db->host.hostname && !host[0] || acl_db->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_db->host.hostname)) { if (!acl_db->db && !db[0] || acl_db->db && !strcmp(db,acl_db->db)) @@ -1141,7 +1141,7 @@ static void init_check_host(void) DBUG_ENTER("init_check_host"); VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), acl_users.elements,1)); - VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0, + VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, (hash_get_key) check_get_key,0,0)); if (!allow_all_hosts) { @@ -1157,7 +1157,7 @@ static void init_check_host(void) { // Check if host already exists acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j, acl_host_and_ip *); - if (!my_strcasecmp(&my_charset_latin1, + if (!my_strcasecmp(system_charset_info, acl_user->host.hostname, acl->hostname)) break; // already stored } @@ -1233,7 +1233,7 @@ bool check_change_password(THD *thd, const char *host, const char *user, } if (!thd->slave_thread && (strcmp(thd->user,user) || - my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip))) + my_strcasecmp(system_charset_info, host, thd->host_or_ip))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) return(1); @@ -1402,7 +1402,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, return (tmp & host->ip_mask) == host->ip; } return (!host->hostname || - (hostname && !wild_case_compare(&my_charset_latin1, + (hostname && !wild_case_compare(system_charset_info, hostname,host->hostname)) || (ip && !wild_compare(ip,host->hostname,0))); } @@ -1415,7 +1415,7 @@ bool hostname_requires_resolving(const char *hostname) int namelen= strlen(hostname); int lhlen= strlen(my_localhost); if ((namelen == lhlen) && - !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen, + !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, (const uchar *)my_localhost, strlen(my_localhost))) return FALSE; for (; (cur=*hostname); hostname++) @@ -1464,8 +1464,8 @@ static bool update_user_table(THD *thd, const char *host, const char *user, if (!(table=open_ltable(thd,&tables,TL_WRITE))) DBUG_RETURN(1); /* purecov: deadcode */ - table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1); - table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1); + table->field[0]->store(host,(uint) strlen(host), system_charset_info); + table->field[1]->store(user,(uint) strlen(user), system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -1478,7 +1478,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user, DBUG_RETURN(1); /* purecov: deadcode */ } store_record(table,record[1]); - table->field[2]->store(new_password, new_password_len, &my_charset_latin1); + table->field[2]->store(new_password, new_password_len, system_charset_info); if ((error=table->file->update_row(table->record[1],table->record[0]))) { table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -1546,8 +1546,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, password=combo.password.str; } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0], 0, (byte*) table->field[0]->ptr, @@ -1581,11 +1581,11 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values table->field[0]->store(combo.host.str,combo.host.length, - &my_charset_latin1); + system_charset_info); table->field[1]->store(combo.user.str,combo.user.length, - &my_charset_latin1); + system_charset_info); table->field[2]->store(password, password_len, - &my_charset_latin1); + system_charset_info); } else { @@ -1596,14 +1596,14 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, DBUG_ASSERT(combo.host.str); if (thd->user && combo.password.str && (strcmp(thd->user,combo.user.str) || - my_strcasecmp(&my_charset_latin1, + my_strcasecmp(system_charset_info, combo.host.str, thd->host_or_ip)) && check_access(thd, UPDATE_ACL, "mysql",0,1,0)) goto end; old_row_exists = 1; store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given - table->field[2]->store(password, password_len, &my_charset_latin1); + table->field[2]->store(password, password_len, system_charset_info); else if (!rights && !revoke_grant && lex->ssl_type == SSL_TYPE_NOT_SPECIFIED && !lex->mqh.bits) { @@ -1648,13 +1648,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, table->field[27]->store("", 0, &my_charset_latin1); if (lex->ssl_cipher) table->field[25]->store(lex->ssl_cipher, - strlen(lex->ssl_cipher), &my_charset_latin1); + strlen(lex->ssl_cipher), system_charset_info); if (lex->x509_issuer) table->field[26]->store(lex->x509_issuer, - strlen(lex->x509_issuer), &my_charset_latin1); + strlen(lex->x509_issuer), system_charset_info); if (lex->x509_subject) table->field[27]->store(lex->x509_subject, - strlen(lex->x509_subject), &my_charset_latin1); + strlen(lex->x509_subject), system_charset_info); break; case SSL_TYPE_NOT_SPECIFIED: break; @@ -1756,9 +1756,9 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(-1); } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, (byte*) table->field[0]->ptr, @@ -1772,9 +1772,9 @@ static int replace_db_table(TABLE *table, const char *db, } old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); } else { @@ -1862,6 +1862,7 @@ public: GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c); GRANT_TABLE (TABLE *form, TABLE *col_privs); + ~GRANT_TABLE(); bool ok() { return privs != 0 || cols != 0; } }; @@ -1887,7 +1888,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; hash_key = (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); } @@ -1911,7 +1912,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) if (!db || !tname) { /* Wrong table row; Ignore it */ - privs = cols = 0; /* purecov: inspected */ + hash_clear(&hash_columns); /* allow for destruction */ + privs= cols= 0; /* purecov: inspected */ return; /* purecov: inspected */ } if (lower_case_table_names) @@ -1928,16 +1930,16 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) privs = fix_rights_for_table(privs); cols = fix_rights_for_column(cols); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); if (cols) { int key_len; col_privs->field[0]->store(orig_host,(uint) strlen(orig_host), - &my_charset_latin1); - col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); - col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); + system_charset_info); + col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info); + col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info); + col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info); key_len=(col_privs->field[0]->pack_length()+ col_privs->field[1]->pack_length()+ col_privs->field[2]->pack_length()+ @@ -1975,6 +1977,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) } +GRANT_TABLE::~GRANT_TABLE() +{ + hash_free(&hash_columns); +} + + static byte* get_grant_table(GRANT_TABLE *buff,uint *length, my_bool not_used __attribute__((unused))) { @@ -2011,15 +2019,15 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, if (exact) { if ((host && - !my_strcasecmp(&my_charset_latin1, host, grant_table->host)) || + !my_strcasecmp(system_charset_info, host, grant_table->host)) || (ip && !strcmp(ip,grant_table->host))) return grant_table; } else { - if (((host && !wild_case_compare(&my_charset_latin1, + if (((host && !wild_case_compare(system_charset_info, host,grant_table->host)) || - (ip && !wild_case_compare(&my_charset_latin1, + (ip && !wild_case_compare(system_charset_info, ip,grant_table->host))) && (!found || found->sort < grant_table->sort)) found=grant_table; // Host ok @@ -2048,10 +2056,10 @@ static int replace_column_table(GRANT_TABLE *g_t, byte key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_column_table"); - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+ table->field[2]->pack_length()+ table->field[3]->pack_length()); key_copy(key,table->record[0],table->key_info,key_length); @@ -2069,7 +2077,7 @@ static int replace_column_table(GRANT_TABLE *g_t, bool old_row_exists=0; key_restore(table->record[0],key,table->key_info,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr, @@ -2088,7 +2096,7 @@ static int replace_column_table(GRANT_TABLE *g_t, restore_record(table,default_values); // Get empty record key_restore(table->record[0],key,table->key_info,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); } else { @@ -2160,7 +2168,7 @@ static int replace_column_table(GRANT_TABLE *g_t, { GRANT_COLUMN *grant_column = NULL; char colum_name_buf[HOSTNAME_LENGTH+1]; - String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1); + String column_name(colum_name_buf,sizeof(colum_name_buf),system_charset_info); privileges&= ~rights; table->field[6]->store((longlong) @@ -2231,10 +2239,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } restore_record(table,default_values); // Get empty record - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); store_record(table,record[1]); // store at pos 1 table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -2279,7 +2287,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } } - table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1); + table->field[4]->store(grantor,(uint) strlen(grantor), system_charset_info); table->field[6]->store((longlong) store_table_rights); table->field[7]->store((longlong) store_col_rights); rights=fix_rights_for_table(store_table_rights); @@ -2694,7 +2702,7 @@ my_bool grant_init(THD *org_thd) DBUG_ENTER("grant_init"); grant_option = FALSE; - (void) hash_init(&column_priv_hash,&my_charset_latin1, + (void) hash_init(&column_priv_hash,system_charset_info, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); @@ -2759,8 +2767,11 @@ my_bool grant_init(THD *org_thd) } } - if (mem_check->ok() && my_hash_insert(&column_priv_hash,(byte*) mem_check)) + if (! mem_check->ok()) + delete mem_check; + else if (my_hash_insert(&column_priv_hash,(byte*) mem_check)) { + delete mem_check; grant_option= FALSE; goto end_unlock; } @@ -3077,9 +3088,9 @@ bool check_grant_db(THD *thd,const char *db) idx); if (len < grant_table->key_length && !memcmp(grant_table->hash_key,helping,len) && - (thd->host && !wild_case_compare(&my_charset_latin1, + (thd->host && !wild_case_compare(system_charset_info, thd->host,grant_table->host) || - (thd->ip && !wild_case_compare(&my_charset_latin1, + (thd->ip && !wild_case_compare(system_charset_info, thd->ip,grant_table->host)))) { error=0; // Found match @@ -3230,7 +3241,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!(host=acl_user->host.hostname)) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) break; } if (counter == acl_users.elements) @@ -3284,7 +3295,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append ("'@'",3); - global.append(lex_user->host.str,lex_user->host.length); + global.append(lex_user->host.str,lex_user->host.length, + system_charset_info); global.append ('\''); if (acl_user->salt_len) { @@ -3318,7 +3330,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append("SUBJECT \'",9); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); + global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), + system_charset_info); global.append('\''); } if (acl_user->ssl_cipher) @@ -3326,7 +3339,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append("CIPHER '",8); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); + global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + system_charset_info); global.append('\''); } } @@ -3365,7 +3379,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { want_access=acl_db->access; if (want_access) @@ -3399,7 +3413,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) db.append(lex_user->user.str, lex_user->user.length, system_charset_info); db.append ("'@'",3); - db.append(lex_user->host.str, lex_user->host.length); + db.append(lex_user->host.str, lex_user->host.length, + system_charset_info); db.append ('\''); if (want_access & GRANT_ACL) db.append(" WITH GRANT OPTION",18); @@ -3425,7 +3440,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) user= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, + !my_strcasecmp(system_charset_info, lex_user->host.str, grant_table->orig_host)) { ulong table_access= grant_table->privs; @@ -3505,7 +3520,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append("'@'",3); - global.append(lex_user->host.str,lex_user->host.length); + global.append(lex_user->host.str,lex_user->host.length, + system_charset_info); global.append('\''); if (table_access & GRANT_ACL) global.append(" WITH GRANT OPTION",18); @@ -3565,6 +3581,27 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); } +/* + Open the grant tables. + + SYNOPSIS + open_grant_tables() + thd The current thread. + tables (out) The 4 elements array for the opened tables. + + DESCRIPTION + Tables are numbered as follows: + 0 user + 1 db + 2 tables_priv + 3 columns_priv + + RETURN + 1 Skip GRANT handling during replication. + 0 OK. + < 0 Error. +*/ + int open_grant_tables(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("open_grant_tables"); @@ -3640,111 +3677,558 @@ ACL_USER *check_acl_user(LEX_USER *user_name, } -bool mysql_drop_user(THD *thd, List &list) +/* + Modify a privilege table. + + SYNOPSIS + modify_grant_table() + table The table to modify. + host_field The host name field. + user_field The user name field. + user_to The new name for the user if to be renamed, + NULL otherwise. + + DESCRIPTION + Update user/host in the current record if user_to is not NULL. + Delete the current record if user_to is NULL. + + RETURN + 0 OK. + != 0 Error. +*/ + +static int modify_grant_table(TABLE *table, Field *host_field, + Field *user_field, LEX_USER *user_to) { - uint counter, acl_userd; - int result; + int error; + DBUG_ENTER("modify_grant_table"); + + if (user_to) + { + /* rename */ + store_record(table, record[1]); + host_field->store(user_to->host.str, user_to->host.length, + system_charset_info); + user_field->store(user_to->user.str, user_to->user.length, + system_charset_info); + if ((error= table->file->update_row(table->record[1], table->record[0]))) + table->file->print_error(error, MYF(0)); + } + else + { + /* delete */ + if ((error=table->file->delete_row(table->record[0]))) + table->file->print_error(error, MYF(0)); + } + + DBUG_RETURN(error); +} + + +/* + Handle a privilege table. + + SYNOPSIS + handle_grant_table() + tables The array with the four open tables. + table_no The number of the table to handle (0..3). + drop If user_from is to be dropped. + user_from The the user to be searched/dropped/renamed. + user_to The new name for the user if to be renamed, + NULL otherwise. + + DESCRIPTION + Scan through all records in a grant table and apply the requested + operation. For the "user" table, a single index access is sufficient, + since there is an unique index on (host, user). + Delete from grant table if drop is true. + Update in grant table if drop is false and user_to is not NULL. + Search in grant table if drop is false and user_to is NULL. + Tables are numbered as follows: + 0 user + 1 db + 2 tables_priv + 3 columns_priv + + RETURN + > 0 At least one record matched. + 0 OK, but no record matched. + < 0 Error. +*/ + +static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + int error; + TABLE *table= tables[table_no].table; + Field *host_field= table->field[0]; + Field *user_field= table->field[table_no ? 2 : 1]; + char *host_str= user_from->host.str; + char *user_str= user_from->user.str; + const char *host; + const char *user; + DBUG_ENTER("handle_grant_table"); + + if (! table_no) // mysql.user table + { + /* + The 'user' table has an unique index on (host, user). + Thus, we can handle everything with a single index access. + The host- and user fields are consecutive in the user table records. + So we set host- and user fields of table->record[0] and use the + pointer to the host field as key. + index_read_idx() will replace table->record[0] (its first argument) + by the searched record, if it exists. + */ + DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'", + table->real_name, user_str, host_str)); + host_field->store(host_str, user_from->host.length, system_charset_info); + user_field->store(user_str, user_from->user.length, system_charset_info); + if ((error= table->file->index_read_idx(table->record[0], 0, + (byte*) host_field->ptr, 0, + HA_READ_KEY_EXACT))) + { + if (error != HA_ERR_KEY_NOT_FOUND) + { + table->file->print_error(error, MYF(0)); + result= -1; + } + } + else + { + /* If requested, delete or update the record. */ + result= ((drop || user_to) && + modify_grant_table(table, host_field, user_field, user_to)) ? + -1 : 1; /* Error or found. */ + } + DBUG_PRINT("info",("read result: %d", result)); + } + else + { + /* + The non-'user' table do not have indexes on (host, user). + And their host- and user fields are not consecutive. + Thus, we need to do a table scan to find all matching records. + */ + if ((error= table->file->ha_rnd_init(1))) + { + table->file->print_error(error, MYF(0)); + result= -1; + } + else + { +#ifdef EXTRA_DEBUG + DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'", + table->real_name, user_str, host_str)); +#endif + while ((error= table->file->rnd_next(table->record[0])) != + HA_ERR_END_OF_FILE) + { + if (error) + { + /* Most probable 'deleted record'. */ + DBUG_PRINT("info",("scan error: %d", error)); + continue; + } + if (! (host= get_field(&mem, host_field))) + host= ""; + if (! (user= get_field(&mem, user_field))) + user= ""; + +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'", + user, host, + get_field(&mem, table->field[1]) /*db*/, + get_field(&mem, table->field[3]) /*table*/, + get_field(&mem, table->field[4]) /*column*/)); +#endif + if (strcmp(user_str, user) || + my_strcasecmp(system_charset_info, host_str, host)) + continue; + + /* If requested, delete or update the record. */ + result= ((drop || user_to) && + modify_grant_table(table, host_field, user_field, user_to)) ? + -1 : result ? result : 1; /* Error or keep result or found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + break ; + } + (void) table->file->ha_rnd_end(); + DBUG_PRINT("info",("scan result: %d", result)); + } + } + + DBUG_RETURN(result); +} + + +/* + Handle an in-memory privilege structure. + + SYNOPSIS + handle_grant_struct() + struct_no The number of the structure to handle (0..2). + drop If user_from is to be dropped. + user_from The the user to be searched/dropped/renamed. + user_to The new name for the user if to be renamed, + NULL otherwise. + + DESCRIPTION + Scan through all elements in an in-memory grant structure and apply + the requested operation. + Delete from grant structure if drop is true. + Update in grant structure if drop is false and user_to is not NULL. + Search in grant structure if drop is false and user_to is NULL. + Structures are numbered as follows: + 0 acl_users + 1 acl_dbs + 2 column_priv_hash + + RETURN + > 0 At least one element matched. + 0 OK, but no element matched. +*/ + +static int handle_grant_struct(uint struct_no, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + uint idx; + uint elements; + const char *user; + const char *host; ACL_USER *acl_user; ACL_DB *acl_db; + GRANT_TABLE *grant_table; + DBUG_ENTER("handle_grant_struct"); + LINT_INIT(acl_user); + LINT_INIT(acl_db); + LINT_INIT(grant_table); + DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'", + struct_no, user_from->user.str, user_from->host.str)); + + /* Get the number of elements in the in-memory structure. */ + switch (struct_no) + { + case 0: + elements= acl_users.elements; + break; + case 1: + elements= acl_dbs.elements; + break; + default: + elements= column_priv_hash.records; + } + +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'", + struct_no, user_from->user.str, user_from->host.str)); +#endif + /* Loop over all elements. */ + for (idx= 0; idx < elements; idx++) + { + /* + Get a pointer to the element. + Unfortunaltely, the host default differs for the structures. + */ + switch (struct_no) + { + case 0: + acl_user= dynamic_element(&acl_users, idx, ACL_USER*); + user= acl_user->user; + if (!(host= acl_user->host.hostname)) + host= "%"; + break; + + case 1: + acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); + user= acl_db->user; + host= acl_db->host.hostname; + break; + + default: + grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, idx); + user= grant_table->user; + host= grant_table->host; + } + if (! user) + user= ""; + if (! host) + host= ""; +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'", + struct_no, idx, user, host)); +#endif + if (strcmp(user_from->user.str, user) || + my_strcasecmp(system_charset_info, user_from->host.str, host)) + continue; + + result= 1; /* At least one element found. */ + if ( drop ) + { + switch ( struct_no ) + { + case 0: + delete_dynamic_element(&acl_users, idx); + break; + + case 1: + delete_dynamic_element(&acl_dbs, idx); + break; + + default: + hash_delete(&column_priv_hash, (byte*) grant_table); + } + elements--; + idx--; + } + else if ( user_to ) + { + switch ( struct_no ) + { + case 0: + acl_user->user= strdup_root(&mem, user_to->user.str); + acl_user->host.hostname= strdup_root(&mem, user_to->host.str); + break; + + case 1: + acl_db->user= strdup_root(&mem, user_to->user.str); + acl_db->host.hostname= strdup_root(&mem, user_to->host.str); + break; + + default: + grant_table->user= strdup_root(&mem, user_to->user.str); + grant_table->host= strdup_root(&mem, user_to->host.str); + } + } + else + { + /* If search is requested, we do not need to search further. */ + break; + } + } +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result)); +#endif + + DBUG_RETURN(result); +} + + +/* + Handle all privilege tables and in-memory privilege structures. + + SYNOPSIS + handle_grant_data() + tables The array with the four open tables. + drop If user_from is to be dropped. + user_from The the user to be searched/dropped/renamed. + user_to The new name for the user if to be renamed, + NULL otherwise. + + DESCRIPTION + Go through all grant tables and in-memory grant structures and apply + the requested operation. + Delete from grant data if drop is true. + Update in grant data if drop is false and user_to is not NULL. + Search in grant data if drop is false and user_to is NULL. + + RETURN + > 0 At least one element matched. + 0 OK, but no element matched. + < 0 Error. +*/ + +static int handle_grant_data(TABLE_LIST *tables, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + int found; + DBUG_ENTER("handle_grant_data"); + + /* Handle user table. */ + if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle user array. */ + if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) || found) + { + result= 1; /* At least one record/element found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + goto end; + } + } + + /* Handle db table. */ + if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle db array. */ + if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) || + found) && ! result) + { + result= 1; /* At least one record/element found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + goto end; + } + } + + /* Handle tables table. */ + if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch columns and in-memory array. */ + result= -1; + } + else + { + if (found && ! result) + { + result= 1; /* At least one record found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + goto end; + } + + /* Handle columns table. */ + if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle columns hash. */ + if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) || + found) && ! result) + result= 1; /* At least one record/element found. */ + } + } + end: + DBUG_RETURN(result); +} + +static void append_user(String *str, LEX_USER *user) +{ + if (str->length()) + str->append(','); + str->append('\''); + str->append(user->user.str); + str->append("'@'"); + str->append(user->host.str); + str->append('\''); +} + +/* + Create a list of users. + + SYNOPSIS + mysql_create_user() + thd The current thread. + list The users to create. + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_create_user(THD *thd, List &list) +{ + int result; + int found; + String wrong_users; + ulong sql_mode; + LEX_USER *user_name; + List_iterator user_list(list); TABLE_LIST tables[4]; + DBUG_ENTER("mysql_create_user"); - DBUG_ENTER("mysql_drop_user"); - + /* CREATE USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) DBUG_RETURN(result != 1); rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); + while ((user_name= user_list++)) + { + /* + Search all in-memory structures and grant tables + for a mention of the new user name. + */ + if ((found= handle_grant_data(tables, 0, user_name, NULL))) + { + append_user(&wrong_users, user_name); + result= TRUE; + continue; + } + + sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_NO_AUTO_CREATE_USER; + if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1)) + { + append_user(&wrong_users, user_name); + result= TRUE; + } + thd->variables.sql_mode= sql_mode; + } + + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr()); + DBUG_RETURN(result); +} + + +/* + Drop a list of users and all their privileges. + + SYNOPSIS + mysql_drop_user() + thd The current thread. + list The users to drop. + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_drop_user(THD *thd, List &list) +{ + int result; + int found; + String wrong_users; LEX_USER *user_name; List_iterator user_list(list); - while ((user_name=user_list++)) + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_drop_user"); + + /* DROP USER may be skipped on replication client. */ + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result != 1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + while ((user_name= user_list++)) { - if (!(acl_user= check_acl_user(user_name, &counter))) + if ((found= handle_grant_data(tables, 1, user_name, NULL)) <= 0) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user", - user_name->user.str, - user_name->host.str); - result= -1; - continue; - } - if ((acl_user->access & ~0)) - { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists", - user_name->user.str, - user_name->host.str); - result= -1; - continue; - } - acl_userd= counter; - - for (counter= 0 ; counter < acl_dbs.elements ; counter++) - { - const char *user,*host; - acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); - if (!(user= acl_db->user)) - user= ""; - if (!(host= acl_db->host.hostname)) - host= ""; - - if (!strcmp(user_name->user.str,user) && - !my_strcasecmp(system_charset_info, user_name->host.str, host)) - break; - } - if (counter != acl_dbs.elements) - { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists", - user_name->user.str, - user_name->host.str); - result= -1; - continue; - } - - for (counter= 0 ; counter < column_priv_hash.records ; counter++) - { - const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - counter); - if (!(user=grant_table->user)) - user= ""; - if (!(host=grant_table->host)) - host= ""; - - if (!strcmp(user_name->user.str,user) && - !my_strcasecmp(system_charset_info, user_name->host.str, host)) - break; - } - if (counter != column_priv_hash.records) - { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists", - user_name->user.str, - user_name->host.str); - result= -1; - continue; - } - - tables[0].table->field[0]->store(user_name->host.str,(uint) - user_name->host.length, - system_charset_info); - tables[0].table->field[1]->store(user_name->user.str,(uint) - user_name->user.length, - system_charset_info); - tables[0].table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); - if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0, - (byte*) tables[0].table-> - field[0]->ptr, - tables[0].table-> - key_info[0].key_length, - HA_READ_KEY_EXACT)) - { - int error; - if ((error = tables[0].table->file->delete_row(tables[0].table-> - record[0]))) - { - tables[0].table->file->print_error(error, MYF(0)); - DBUG_RETURN(TRUE); - } - delete_dynamic_element(&acl_users, acl_userd); + append_user(&wrong_users, user_name); + result= TRUE; } } @@ -3752,10 +4236,81 @@ bool mysql_drop_user(THD *thd, List &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); if (result) - my_message(ER_DROP_USER, ER(ER_DROP_USER), MYF(0)); + my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr()); DBUG_RETURN(result); } + +/* + Rename a user. + + SYNOPSIS + mysql_rename_user() + thd The current thread. + list The user name pairs: (from, to). + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_rename_user(THD *thd, List &list) +{ + int result= 0; + int found; + String wrong_users; + LEX_USER *user_from; + LEX_USER *user_to; + List_iterator user_list(list); + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_rename_user"); + + /* RENAME USER may be skipped on replication client. */ + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result != 1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + while ((user_from= user_list++)) + { + user_to= user_list++; + DBUG_ASSERT(user_to); /* Syntax enforces pairs of users. */ + + /* + Search all in-memory structures and grant tables + for a mention of the new user name. + */ + if (handle_grant_data(tables, 0, user_to, NULL) || + handle_grant_data(tables, 0, user_from, user_to) <= 0) + { + append_user(&wrong_users, user_from); + result= TRUE; + } + } + + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr()); + DBUG_RETURN(result); +} + +/* + Revoke all privileges from a list of users. + + SYNOPSIS + mysql_revoke_all() + thd The current thread. + list The users to revoke all privileges from. + + RETURN + > 0 Error. Error message already sent. + 0 OK. + < 0 Error. Error message not yet sent. +*/ + bool mysql_revoke_all(THD *thd, List &list) { uint counter, revoked; @@ -3801,13 +4356,13 @@ bool mysql_revoke_all(THD *thd, List &list) for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; ) { const char *user,*host; - + acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user=acl_db->user)) user= ""; if (!(host=acl_db->host.hostname)) host= ""; - + if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { @@ -3838,7 +4393,7 @@ bool mysql_revoke_all(THD *thd, List &list) user= ""; if (!(host=grant_table->host)) host= ""; - + if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { @@ -3873,14 +4428,14 @@ bool mysql_revoke_all(THD *thd, List &list) } } while (revoked); } - + VOID(pthread_mutex_unlock(&acl_cache->lock)); rw_unlock(&LOCK_grant); close_thread_tables(thd); - + if (result) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); - + DBUG_RETURN(result); } diff --git a/sql/sql_acl.h b/sql/sql_acl.h index f6074da5279..8f3ee072f43 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -182,7 +182,9 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, bool mysql_show_grants(THD *thd, LEX_USER *user); void get_privilege_desc(char *to, uint max_length, ulong access); void get_mqh(const char *user, const char *host, USER_CONN *uc); +bool mysql_create_user(THD *thd, List &list); bool mysql_drop_user(THD *thd, List &list); +bool mysql_rename_user(THD *thd, List &list); bool mysql_revoke_all(THD *thd, List &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ae2261e19f9..cc178a3121b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1754,7 +1754,8 @@ bool select_dumpvar::send_data(List &items) bool select_dumpvar::send_eof() { if (! row_count) - send_warning(thd, ER_SP_FETCH_NO_DATA); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA)); ::send_ok(thd,row_count); return 0; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 63741bcb176..ce37318ca01 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -201,7 +201,7 @@ static int find_keyword(LEX *lex, uint len, bool function) lex->yylval->symbol.length=len; if ((symbol->tok == NOT_SYM) && - (lex->thd->variables.sql_mode & MODE_BROKEN_NOT)) + (lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE)) return NOT2_SYM; if ((symbol->tok == OR_OR_SYM) && !(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT)) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 605204fe35d..e99e6138b6d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,8 @@ enum enum_sql_command { SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, - SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, + SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER, + SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL, SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION, SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC, @@ -282,8 +283,9 @@ public: } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) {} - static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) {} + static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) + { TRASH(ptr, size); } st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} virtual ~st_select_lex_node() {} inline st_select_lex_node* get_master() { return master; } @@ -650,7 +652,6 @@ typedef struct st_lex char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ char* to_log; /* For PURGE MASTER LOGS TO */ - time_t purge_time; /* For PURGE MASTER LOGS BEFORE */ char* x509_subject,*x509_issuer,*ssl_cipher; char* found_colon; /* For multi queries - next query */ String *wild; @@ -694,7 +695,7 @@ typedef struct st_lex HA_CREATE_INFO create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER USER_RESOURCES mqh; - ulong thread_id,type; + ulong type; enum_sql_command sql_command, orig_sql_command; thr_lock_type lock_option, multi_lock_option; enum SSL_type ssl_type; /* defined in violite.h */ @@ -820,7 +821,8 @@ struct st_lex_local: public st_lex { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) {} + static void operator delete(void *ptr,size_t size) + { TRASH(ptr, size); } }; void lex_init(void); diff --git a/sql/sql_list.h b/sql/sql_list.h index 141742c3d4a..657943f1e69 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -21,12 +21,6 @@ /* mysql standard class memory allocator */ -#ifdef SAFEMALLOC -#define TRASH(XX,YY) bfill((XX), (YY), 0x8F) -#else -#define TRASH(XX,YY) /* no-op */ -#endif - class Sql_alloc { public: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fce8d294456..c04312f6ded 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1175,9 +1175,13 @@ end: void free_items(Item *item) { + Item *next; DBUG_ENTER("free_items"); - for (; item ; item=item->next) + for (; item ; item=next) + { + next=item->next; item->delete_self(); + } DBUG_VOID_RETURN; } @@ -2327,10 +2331,24 @@ mysql_execute_command(THD *thd) } case SQLCOM_PURGE_BEFORE: { + Item *it; + if (check_global_access(thd, SUPER_ACL)) goto error; /* PURGE MASTER LOGS BEFORE 'data' */ - res = purge_master_logs_before_date(thd, lex->purge_time); + it= (Item *)lex->value_list.head(); + if (it->check_cols(1) || it->fix_fields(lex->thd, 0, &it)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); + goto error; + } + it= new Item_func_unix_timestamp(it); + /* + it is OK only emulate fix_fieds, because we need only + value of constant + */ + it->quick_fix_field(); + res = purge_master_logs_before_date(thd, (ulong)it->val_int()); break; } #endif @@ -3370,6 +3388,21 @@ create_error: break; } #ifndef NO_EMBEDDED_ACCESS_CHECKS + case SQLCOM_CREATE_USER: + { + if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) + break; + if (!(res= mysql_create_user(thd, lex->users_list))) + { + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } case SQLCOM_DROP_USER: { if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) @@ -3378,8 +3411,23 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } + case SQLCOM_RENAME_USER: + { + if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) + break; + if (!(res= mysql_rename_user(thd, lex->users_list))) + { + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); } send_ok(thd); } @@ -3505,8 +3553,18 @@ create_error: break; } case SQLCOM_KILL: - kill_one_thread(thd,lex->thread_id, lex->type & ONLY_KILL_QUERY); + { + Item *it= (Item *)lex->value_list.head(); + + if (it->fix_fields(lex->thd, 0, &it) || it->check_cols(1)) + { + my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), + MYF(0)); + goto error; + } + kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY); break; + } #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: if ((thd->priv_user && @@ -3594,9 +3652,10 @@ create_error: message in the error log, so we don't send it. */ if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - send_warning(thd,ER_WARNING_NOT_COMPLETE_ROLLBACK,0); - else - send_ok(thd); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); } else res= TRUE; @@ -3606,9 +3665,10 @@ create_error: if (!ha_rollback_to_savepoint(thd, lex->savepoint_name)) { if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - send_warning(thd, ER_WARNING_NOT_COMPLETE_ROLLBACK, 0); - else - send_ok(thd); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); } else goto error; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d2e3e72618d..0d1a7f3890d 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -779,7 +779,8 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) thread_mask&= thd->lex->slave_thd_opt; if (thread_mask) //some threads are stopped, start them { - if (init_master_info(mi,master_info_file,relay_log_info_file, 0)) + if (init_master_info(mi,master_info_file,relay_log_info_file, 0, + thread_mask)) slave_errno=ER_MASTER_INFO; else if (server_id_supplied && *mi->host) { @@ -1074,7 +1075,8 @@ bool change_master(THD* thd, MASTER_INFO* mi) thd->proc_info = "Changing master"; LEX_MASTER_INFO* lex_mi= &thd->lex->mi; // TODO: see if needs re-write - if (init_master_info(mi, master_info_file, relay_log_info_file, 0)) + if (init_master_info(mi, master_info_file, relay_log_info_file, 0, + thread_mask)) { my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); unlock_slave_threads(mi); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93ed04be4b2..fb8e074ebf8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -263,11 +263,13 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, save_allow_sum_func= thd->allow_sum_func; thd->allow_sum_func= 0; - res= (setup_conds(thd, tables, leaves, conds) || - setup_order(thd, ref_pointer_array, tables, fields, all_fields, - order) || - setup_group(thd, ref_pointer_array, tables, fields, all_fields, - group, hidden_group_fields)); + res= setup_conds(thd, tables, leaves, conds); + thd->allow_sum_func= save_allow_sum_func; + res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, + order); + thd->allow_sum_func= 0; + res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields, + group, hidden_group_fields); thd->allow_sum_func= save_allow_sum_func; DBUG_RETURN(res); } @@ -6023,9 +6025,13 @@ static void clear_tables(JOIN *join) class COND_CMP :public ilink { public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } static void operator delete(void *ptr __attribute__((unused)), - size_t size __attribute__((unused))) {} /*lint -e715 */ + size_t size __attribute__((unused))) + { TRASH(ptr, size); } Item *and_level; Item_func *cmp_func; @@ -11346,7 +11352,7 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, setup_group() thd Thread handler ref_pointer_array We store references to all fields that was not in - 'fields' here. + 'fields' here. fields All fields in the select part. Any item in 'order' that is part of these list is replaced by a pointer to this fields. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 55c38ff37c9..eb9ca43b56a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1257,9 +1257,13 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) class thread_info :public ilink { public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } static void operator delete(void *ptr __attribute__((unused)), - size_t size __attribute__((unused))) {} /*lint -e715 */ + size_t size __attribute__((unused))) + { TRASH(ptr, size); } ulong thread_id; time_t start_time; @@ -2628,7 +2632,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, { CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_stat_record"); - if (!res) + if (!res && !tables->view) { TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; @@ -2737,7 +2741,7 @@ static int get_schema_constarints_record(THD *thd, struct st_table_list *tables, { CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_constarints_record"); - if (!res) + if (!res && !tables->view) { List f_key_list; TABLE *show_table= tables->table; @@ -2792,7 +2796,7 @@ static int get_schema_key_column_usage_record(THD *thd, { DBUG_ENTER("get_schema_key_column_usage_record"); CHARSET_INFO *cs= system_charset_info; - if (!res) + if (!res && !tables->view) { List f_key_list; TABLE *show_table= tables->table; @@ -2960,7 +2964,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->options | TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, table_list->real_name))) + HA_POS_ERROR, table_list->alias))) DBUG_RETURN(0); DBUG_RETURN(table); } @@ -3136,6 +3140,9 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) } table->tmp_table= TMP_TABLE; table->grant.privilege= SELECT_ACL; + table->alias_name_used= my_strcasecmp(table_alias_charset, + table_list->real_name, + table_list->alias); table_list->schema_table_name= table_list->real_name; table_list->real_name= table->real_name; table_list->table= table; diff --git a/sql/sql_string.h b/sql/sql_string.h index 2101db40f92..cb9db52c830 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -72,9 +72,9 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr_arg,size_t size) - {} + { TRASH(ptr_arg, size); } static void operator delete(void *ptr_arg,size_t size, MEM_ROOT *mem_root) - {} + { TRASH(ptr_arg, size); } ~String() { free(); } inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 81d8000831b..ec63bb92c54 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -684,7 +684,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) mark to avoid temporary table using and put view reference and find last view table */ - for (TABLE_LIST *tbl= view_tables; + for (tbl= view_tables; tbl; tbl= (view_tables_tail= tbl)->next_global) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dd9cd4af0f3..74a96701bdc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -788,9 +788,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id - opt_column_list grant_privileges opt_table user_list grant_option - grant_privilege grant_privilege_list - flush_options flush_option + opt_column_list grant_privileges opt_table grant_list grant_option + grant_privilege grant_privilege_list user_list rename_list + clear_privileges flush_options flush_option equal optional_braces opt_key_definition key_usage_list2 opt_mi_check_type opt_to mi_check_types normal_join table_to_table_list table_to_table opt_table_list opt_as @@ -1287,8 +1287,26 @@ create: TL_WRITE)) YYABORT; } + | CREATE USER clear_privileges grant_list + { + Lex->sql_command = SQLCOM_CREATE_USER; + } ; +clear_privileges: + /* Nothing */ + { + LEX *lex=Lex; + lex->users_list.empty(); + lex->columns.empty(); + lex->grant= lex->grant_tot_col= 0; + lex->select_lex.db= 0; + lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; + lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; + bzero((char *)&(lex->mqh),sizeof(lex->mqh)); + } + ; + sp_name: IDENT_sys '.' IDENT_sys { @@ -3671,8 +3689,25 @@ rename: } table_to_table_list {} + | RENAME USER clear_privileges rename_list + { + Lex->sql_command = SQLCOM_RENAME_USER; + } ; +rename_list: + user TO_SYM user + { + if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3)) + YYABORT; + } + | rename_list ',' user TO_SYM user + { + if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5)) + YYABORT; + } + ; + table_to_table_list: table_to_table | table_to_table_list ',' table_to_table; @@ -5479,14 +5514,10 @@ drop: lex->drop_if_exists= $3; lex->spname= $4; } - | DROP USER + | DROP USER clear_privileges user_list { - LEX *lex=Lex; - lex->sql_command = SQLCOM_DROP_USER; - lex->users_list.empty(); - } - user_list - {} + Lex->sql_command = SQLCOM_DROP_USER; + } | DROP VIEW_SYM if_exists table_list opt_restrict { THD *thd= YYTHD; @@ -6280,19 +6311,10 @@ purge_option: } | BEFORE_SYM expr { - if ($2->check_cols(1) || $2->fix_fields(Lex->thd, 0, &$2)) - { - my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); - YYABORT; - } - Item *tmp= new Item_func_unix_timestamp($2); - /* - it is OK only emulate fix_fieds, because we need only - value of constant - */ - tmp->quick_fix_field(); - Lex->sql_command = SQLCOM_PURGE_BEFORE; - Lex->purge_time= (ulong) tmp->val_int(); + LEX *lex= Lex; + lex->value_list.empty(); + lex->value_list.push_front($2); + lex->sql_command= SQLCOM_PURGE_BEFORE; } ; @@ -6302,14 +6324,9 @@ kill: KILL_SYM kill_option expr { LEX *lex=Lex; - if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1)) - { - my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), - MYF(0)); - YYABORT; - } - lex->sql_command=SQLCOM_KILL; - lex->thread_id= (ulong) $3->val_int(); + lex->value_list.empty(); + lex->value_list.push_front($3); + lex->sql_command= SQLCOM_KILL; }; kill_option: @@ -7478,48 +7495,28 @@ handler_rkey_mode: /* GRANT / REVOKE */ revoke: - REVOKE - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_REVOKE; - lex->users_list.empty(); - lex->columns.empty(); - lex->grant= lex->grant_tot_col=0; - lex->select_lex.db=0; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char*) &lex->mqh, sizeof(lex->mqh)); - } - revoke_command + REVOKE clear_privileges revoke_command {} ; revoke_command: - grant_privileges ON opt_table FROM user_list - {} + grant_privileges ON opt_table FROM grant_list + { + Lex->sql_command = SQLCOM_REVOKE; + } | - ALL opt_privileges ',' GRANT OPTION FROM user_list + ALL opt_privileges ',' GRANT OPTION FROM grant_list { Lex->sql_command = SQLCOM_REVOKE_ALL; } ; grant: - GRANT - { - LEX *lex=Lex; - lex->users_list.empty(); - lex->columns.empty(); - lex->sql_command = SQLCOM_GRANT; - lex->grant= lex->grant_tot_col= 0; - lex->select_lex.db= 0; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char *)&(lex->mqh),sizeof(lex->mqh)); - } - grant_privileges ON opt_table TO_SYM user_list + GRANT clear_privileges grant_privileges ON opt_table TO_SYM grant_list require_clause grant_options - {} + { + Lex->sql_command = SQLCOM_GRANT; + } ; grant_privileges: @@ -7659,8 +7656,18 @@ opt_table: user_list: + user { if (Lex->users_list.push_back($1)) YYABORT;} + | user_list ',' user + { + if (Lex->users_list.push_back($3)) + YYABORT; + } + ; + + +grant_list: grant_user { if (Lex->users_list.push_back($1)) YYABORT;} - | user_list ',' grant_user + | grant_list ',' grant_user { if (Lex->users_list.push_back($3)) YYABORT; diff --git a/strings/decimal.c b/strings/decimal.c index b8e8fd3725f..b88be6116a6 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -503,7 +503,7 @@ int decimal2ulonglong(decimal *from, ulonglong *to) { dec1 *buf=from->buf; ulonglong x=0; - int intg; + int intg, frac; if (from->sign) { @@ -515,21 +515,24 @@ int decimal2ulonglong(decimal *from, ulonglong *to) { ulonglong y=x; x=x*DIG_BASE + *buf++; - if (unlikely(x < y)) + if (unlikely(y > (ULONGLONG_MAX/DIG_BASE) || x < y)) { *to=y; return E_DEC_OVERFLOW; } } *to=x; - return from->frac ? E_DEC_TRUNCATED : E_DEC_OK; + for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1) + if (*buf++) + return E_DEC_TRUNCATED; + return E_DEC_OK; } int decimal2longlong(decimal *from, longlong *to) { dec1 *buf=from->buf; longlong x=0; - int intg; + int intg, frac; for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) { @@ -537,11 +540,11 @@ int decimal2longlong(decimal *from, longlong *to) /* Attention: trick! we're calculating -|from| instead of |from| here - because |MIN_LONGLONG| > MAX_LONGLONG + because |LONGLONG_MIN| > LONGLONG_MAX so we can convert -9223372036854775808 correctly */ x=x*DIG_BASE - *buf++; - if (unlikely(x > y)) + if (unlikely(y < (LONGLONG_MAX/DIG_BASE) || x > y)) { *to= from->sign ? y : -y; return E_DEC_OVERFLOW; @@ -555,7 +558,10 @@ int decimal2longlong(decimal *from, longlong *to) } *to=from->sign ? x : -x; - return from->frac ? E_DEC_TRUNCATED : E_DEC_OK; + for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1) + if (*buf++) + return E_DEC_TRUNCATED; + return E_DEC_OK; } /* @@ -867,7 +873,7 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode error=E_DEC_TRUNCATED; } - if (scale+from->intg <0) + if (scale+from->intg <= 0) { decimal_make_zero(to); return E_DEC_OK; @@ -1928,6 +1934,7 @@ main() test_d2ull("18446744073709551616"); test_d2ull("-1"); test_d2ull("1.23"); + test_d2ull("9999999999999999999999999.000"); printf("==== longlong2decimal ====\n"); test_ll2d(LL(-12345));