From ec8617c693dc9e2343ec161b4cc729245d5c4ec4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Jul 2005 12:07:47 -0700 Subject: [PATCH 01/80] Fix shortcircuit of 127.0.0.1 -> localhost lookup on little-endian machines. (Bug #11822) sql/hostname.cc: Fix comparison against INADDR_LOOPBACK to deal with endianness. --- sql/hostname.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/hostname.cc b/sql/hostname.cc index 12b69a97859..af9bc56ccb3 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -143,8 +143,8 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) *errors=0; /* We always treat the loopback address as "localhost". */ - if (in->s_addr == INADDR_LOOPBACK) - return (char *)my_localhost; + if (in->s_addr == htonl(INADDR_LOOPBACK)) + DBUG_RETURN((char *)my_localhost); /* Check first if we have name in cache */ if (!(specialflag & SPECIAL_NO_HOST_CACHE)) From c8cd901b33e7c4b757bb3977d7920a22710dd68e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Jul 2005 16:12:17 +0200 Subject: [PATCH 02/80] ndb - only run ndb_config test when using "default" config mysql-test/t/ndb_config.test: only run ndb_config test when using "default" config --- mysql-test/t/ndb_config.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test index ea78a32b1ba..a79973515b2 100644 --- a/mysql-test/t/ndb_config.test +++ b/mysql-test/t/ndb_config.test @@ -1,4 +1,5 @@ -- source include/have_ndb.inc +-- source include/ndb_default_cluster.inc -- source include/not_embedded.inc --exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=type,nodeid,host 2> /dev/null From d953bc7a648b57dd138fb558a3de4e3858415275 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Aug 2005 15:13:56 -0600 Subject: [PATCH 03/80] Added a test case for BUG#10456 mysql-test/r/rpl_insert_select.result: New BitKeeper file ``mysql-test/r/rpl_insert_select.result'' --- mysql-test/r/rpl_insert_select.result | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 mysql-test/r/rpl_insert_select.result diff --git a/mysql-test/r/rpl_insert_select.result b/mysql-test/r/rpl_insert_select.result new file mode 100644 index 00000000000..1aff39e0026 --- /dev/null +++ b/mysql-test/r/rpl_insert_select.result @@ -0,0 +1,17 @@ +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; +create table t1 (n int not null primary key); +insert into t1 values (1); +create table t2 (n int); +insert into t2 values (1); +insert ignore into t1 select * from t2; +insert into t1 values (2); +select * from t1; +n +1 +2 +drop table t1,t2; From bbb2bfe1b7386ea7c87e671d06175dc1b1e4c760 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Aug 2005 15:15:28 -0600 Subject: [PATCH 04/80] The earlier commit for BUG#10456 did not add the test file mysql-test/t/rpl_insert_select.test: New BitKeeper file ``mysql-test/t/rpl_insert_select.test'' --- mysql-test/t/rpl_insert_select.test | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 mysql-test/t/rpl_insert_select.test diff --git a/mysql-test/t/rpl_insert_select.test b/mysql-test/t/rpl_insert_select.test new file mode 100644 index 00000000000..677be526982 --- /dev/null +++ b/mysql-test/t/rpl_insert_select.test @@ -0,0 +1,19 @@ +# Testcase for BUG#10456 - INSERT INTO ... SELECT violating a primary key +# breaks replication + +-- source include/master-slave.inc +connection master; + +create table t1 (n int not null primary key); +insert into t1 values (1); +create table t2 (n int); +insert into t2 values (1); +insert ignore into t1 select * from t2; +insert into t1 values (2); +sync_slave_with_master; +connection slave; +select * from t1; + +connection master; +drop table t1,t2; +sync_slave_with_master; From ec657e8d2a350ba94cecc6e6fbf1809682d93fd3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 3 Aug 2005 18:08:20 -0600 Subject: [PATCH 05/80] patch for BUG#4680 - drop database breaking replication if there were extra files in the database directory on the master mysql-test/r/rpl_drop_db.result: New BitKeeper file ``mysql-test/r/rpl_drop_db.result'' mysql-test/t/rpl_drop_db.test: New BitKeeper file ``mysql-test/t/rpl_drop_db.test'' --- mysql-test/r/rpl_drop_db.result | 30 ++++++++++++++++++++++ mysql-test/t/rpl_drop_db.test | 39 ++++++++++++++++++++++++++++ sql/mysql_priv.h | 2 +- sql/sql_db.cc | 45 +++++++++++++++++++++++++++++---- sql/sql_table.cc | 20 ++++++++++++++- 5 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 mysql-test/r/rpl_drop_db.result create mode 100644 mysql-test/t/rpl_drop_db.test diff --git a/mysql-test/r/rpl_drop_db.result b/mysql-test/r/rpl_drop_db.result new file mode 100644 index 00000000000..bafbfe3a1ed --- /dev/null +++ b/mysql-test/r/rpl_drop_db.result @@ -0,0 +1,30 @@ +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; +drop database if exists d1; +create database d1; +create table d1.t1 (n int); +insert into d1.t1 values (1); +select * from d1.t1 into outfile 'd1/f1.txt'; +create table d1.t2 (n int); +create table d1.t3 (n int); +drop database d1; +ERROR HY000: Error dropping database (can't rmdir './d1/', errno: 17) +use d1; +show tables; +Tables_in_d1 +use test; +create table t1 (n int); +insert into t1 values (1234); +use d1; +show tables; +Tables_in_d1 +use test; +select * from t1; +n +1234 +drop table t1; +stop slave; diff --git a/mysql-test/t/rpl_drop_db.test b/mysql-test/t/rpl_drop_db.test new file mode 100644 index 00000000000..ef0ab4be6fd --- /dev/null +++ b/mysql-test/t/rpl_drop_db.test @@ -0,0 +1,39 @@ +# test case for BUG#4680 -- if there are extra files in the db directory +# dropping the db on the master causes replication problems + +-- source include/master-slave.inc +connection master; + +--disable_warnings +drop database if exists d1; +--enable_warnings +create database d1; +create table d1.t1 (n int); +insert into d1.t1 values (1); +select * from d1.t1 into outfile 'd1/f1.txt'; +create table d1.t2 (n int); +create table d1.t3 (n int); +--error 1010 +drop database d1; +use d1; +show tables; +use test; +create table t1 (n int); +insert into t1 values (1234); +sync_slave_with_master; + +connection slave; +use d1; +show tables; +use test; +select * from t1; + +connection master; +drop table t1; +sync_slave_with_master; + +#cleanup +connection slave; +stop slave; +system rm -rf var/master-data/d1; + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6969433649f..9d46cc507df 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -441,7 +441,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool log_query); int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, - bool log_query); + bool log_query, List *dropped_tables); int quick_rm_table(enum db_type base,const char *db, const char *table_name); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index ad6845572e1..0155fca0466 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -31,7 +31,7 @@ static TYPELIB deletable_extentions= static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, - uint level); + uint level, List *dropped_tables); /* Database options hash */ static HASH dboptions; @@ -584,6 +584,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) int error= 0; char path[FN_REFLEN+16], tmp_db[NAME_LEN+1]; MY_DIR *dirp; + List dropped_tables; uint length; DBUG_ENTER("mysql_rm_db"); @@ -621,8 +622,10 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) remove_db_from_cache(db); pthread_mutex_unlock(&LOCK_open); + error= -1; - if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0)) >= 0) + if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0, + &dropped_tables)) >= 0) { ha_drop_database(path); query_cache_invalidate1(db); @@ -672,6 +675,37 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) send_ok(thd, (ulong) deleted); thd->server_status&= ~SERVER_STATUS_DB_DROPPED; } + else if (!dropped_tables.is_empty() && mysql_bin_log.is_open()) + { + List_iterator it(dropped_tables); + String* dropped_table; + int q_len= 11; /* drop table */ + int db_len= strlen(db); + + for (;(dropped_table= it++);) + { + q_len += dropped_table->length() + 2 + db_len; + } + q_len--; /* no last comma */ + + char* query= thd->alloc(q_len); + if (!query) + goto exit; /* not much else we can do */ + char* p= strmov(query,"drop table "); + it.rewind(); + + for (;(dropped_table= it++);) + { + p= strmov(p,db); + *p++ = '.'; + p= strnmov(p,dropped_table->ptr(),dropped_table->length()); + *p++ = ','; + } + *--p= 0; + Query_log_event qinfo(thd, query, q_len, 0, 0); + qinfo.error_code= 0; + mysql_bin_log.write(&qinfo); + } exit: start_waiting_global_read_lock(thd); @@ -716,7 +750,7 @@ exit2: */ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, - const char *org_path, uint level) + const char *org_path, uint level, List *dropped_tables) { long deleted=0; ulong found_other_files=0; @@ -758,7 +792,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) { DBUG_PRINT("my",("New subdir found: %s", newpath)); - if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0) + if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0) goto err; if (!(copy_of_path= thd->memdup(newpath, length+1)) || !(dir= new (thd->mem_root) String(copy_of_path, length, @@ -805,7 +839,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, } } if (thd->killed || - (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1))) + (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, + 1,dropped_tables))) goto err; /* Remove RAID directories */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 87b864c73fa..e948a65f301 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -156,7 +156,8 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, bool if_exists, - bool drop_temporary, bool dont_log_query) + bool drop_temporary, bool dont_log_query, + List* dropped_tables) { int error; thd->mysys_var->current_mutex= &LOCK_open; @@ -165,6 +166,23 @@ int mysql_rm_table_part2_with_lock(THD *thd, error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, dont_log_query); + /* + For now we assume that if we got success all the tables in the list + were actually dropped, otherwise, assume none were dropped. + TODO: fix it to work with a partial drop - extremely rare case, but + can happen. + */ + if (!error && dropped_tables) + { + TABLE_LIST* tbl; + + for (tbl= tables; tbl; tbl= tbl->next) + { + String *dropped_table= new (thd->mem_root) + String(tbl->real_name,&my_charset_latin1); + dropped_tables->push_back(dropped_table); + } + } pthread_mutex_unlock(&LOCK_open); From 06ebdbb7859ebdfa1d3ba97a45bf74224619b384 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Aug 2005 22:13:43 +0400 Subject: [PATCH 06/80] Fix bug #11398 Bug in field_conv() results in wrong result of join with index When copying varchar fields with field_conv() it's not taken into account that length_bytes of source and destination fields may be different. This results in saving wrong data in field and making wrong key later. Added check so if fields are varchar and have different length_bytes they are not copied by memcpy(). sql/field_conv.cc: Fix bug #11398 Bug in field_conv() results in wrong result of join with index mysql-test/t/select.test: Test case for bug #11398 Bug in field_conv() results in wrong result of join with index mysql-test/r/select.result: Test case for bug #11398 Bug in field_conv() results in wrong result of join with index --- mysql-test/r/select.result | 9 +++++++++ mysql-test/t/select.test | 10 ++++++++++ sql/field_conv.cc | 5 ++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index d3409bf8d39..4cbe652552f 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2739,3 +2739,12 @@ DROP TABLE t1,t2; select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0; x'10' + 0 X'10' + 0 b'10' + 0 B'10' + 0 16 16 2 2 +create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null); +create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4)); +insert into t1 values (" 2", 2); +insert into t2 values (" 2", " one "),(" 2", " two "); +select * from t1 left join t2 on f1 = f3; +f1 f2 f3 f4 + 2 2 2 one + 2 2 2 two +drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 1de0831ad84..b7b09c36543 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2350,3 +2350,13 @@ DROP TABLE t1,t2; # select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0; + +# +# Bug #11398 Bug in field_conv() results in wrong result of join with index +# +create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null); +create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4)); +insert into t1 values (" 2", 2); +insert into t2 values (" 2", " one "),(" 2", " two "); +select * from t1 left join t2 on f1 = f3; +drop table t1,t2; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index fc7347ef9af..40f3ff85c58 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -640,7 +640,10 @@ void field_conv(Field *to,Field *from) (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || to->type() != FIELD_TYPE_DATE && - to->type() != FIELD_TYPE_DATETIME)) + to->type() != FIELD_TYPE_DATETIME) && + (from->real_type() != MYSQL_TYPE_VARCHAR || + ((Field_varstring*)from)->length_bytes == + ((Field_varstring*)to)->length_bytes)) { // Identical fields #ifdef HAVE_purify /* This may happen if one does 'UPDATE ... SET x=x' */ From 685fae21d4fdcf603c0f7c66e6d41b761ce58665 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 11:56:04 +0300 Subject: [PATCH 07/80] Fix bug #12588, InnoDB's deadlock detector running out of stack space. innobase/lock/lock0lock.c: Limit recursion depth in lock_deadlock_recursive to 200. --- innobase/lock/lock0lock.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 1f222d71d6a..7844991613f 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -47,6 +47,10 @@ innobase_mysql_end_print_arbitrary_thd(void); graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 +/* Restricts the recursion depth of the search we will do in the waits-for +graph of transactions */ +#define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200 + /* When releasing transaction locks, this specifies how often we release the kernel mutex for a moment to give also others access to it */ @@ -389,9 +393,12 @@ lock_deadlock_recursive( trx_t* start, /* in: recursion starting point */ trx_t* trx, /* in: a transaction waiting for a lock */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ - ulint* cost); /* in/out: number of calculation steps thus + ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... - we return TRUE */ + we return LOCK_VICTIM_IS_START */ + uint depth); /* in: recursion depth: if this exceeds + LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we + return LOCK_VICTIM_IS_START */ /************************************************************************* Gets the type of a lock. */ @@ -3180,7 +3187,7 @@ retry: mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx); } - ret = lock_deadlock_recursive(trx, trx, lock, &cost); + ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0); if (ret == LOCK_VICTIM_IS_OTHER) { /* We chose some other trx as a victim: retry if there still @@ -3226,9 +3233,12 @@ lock_deadlock_recursive( trx_t* start, /* in: recursion starting point */ trx_t* trx, /* in: a transaction waiting for a lock */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ - ulint* cost) /* in/out: number of calculation steps thus + ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ + uint depth) /* in: recursion depth: if this exceeds + LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we + return LOCK_VICTIM_IS_START */ { lock_t* lock; ulint bit_no = ULINT_UNDEFINED; @@ -3249,7 +3259,8 @@ lock_deadlock_recursive( *cost = *cost + 1; - if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) { + if ((depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK) + || (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)) { return(LOCK_VICTIM_IS_START); } @@ -3375,7 +3386,7 @@ lock_deadlock_recursive( a lock */ ret = lock_deadlock_recursive(start, lock_trx, - lock_trx->wait_lock, cost); + lock_trx->wait_lock, cost, depth + 1); if (ret != 0) { return(ret); From 513ba182b0a867d682b3433ea9dae1f227a6f0da Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 15:11:29 +0200 Subject: [PATCH 08/80] No C++ style comments in C source! --- mysys/charset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/charset.c b/mysys/charset.c index df3f1cfa279..5aaac7a178f 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -679,5 +679,5 @@ char *bare_str_to_hex(char *to, const char *from, uint len) p[1]= _dig_vec_upper[tmp & 15]; } *p= 0; - return p; // pointer to end 0 of 'to' + return p; /* pointer to end 0 of 'to' */ } From cf7b1241d12303df480fde5795ebe24c8e9c26d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 22:42:53 +0300 Subject: [PATCH 09/80] sql_view.cc: correct exit from mysql_create_view to restore ennvironment (BUG#12468) view.result, view.test: test of CRETE VIEW in SP mysql-test/t/view.test: test of CRETE VIEW in SP mysql-test/r/view.result: test of CRETE VIEW in SP sql/sql_view.cc: correct exit from mysql_create_view to restore ennvironment --- mysql-test/r/view.result | 8 ++++++++ mysql-test/t/view.test | 12 ++++++++++++ sql/sql_view.cc | 21 ++++++++++++++++----- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 2af2f06ad52..43df10b40dd 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2097,3 +2097,11 @@ select * from v1; f1 1 drop view v1; +create table t1(a int); +create procedure p1() create view v1 as select * from t1; +drop table t1; +call p1(); +ERROR 42S02: Table 'test.t1' doesn't exist +call p1(); +ERROR 42S02: Table 'test.t1' doesn't exist +drop procedure p1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index ceff7af401c..c185c9b1c86 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1942,3 +1942,15 @@ DROP TABLE t1,t2,t3,t4,t5; create view v1 as select timestampdiff(day,'1997-01-01 00:00:00','1997-01-02 00:00:00') as f1; select * from v1; drop view v1; + +# +# repeatable CREATE VIEW statement BUG#12468 +# +create table t1(a int); +create procedure p1() create view v1 as select * from t1; +drop table t1; +-- error 1146 +call p1(); +-- error 1146 +call p1(); +drop procedure p1; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c3222f951bb..1881cdc324f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -234,7 +234,10 @@ bool mysql_create_view(THD *thd, (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 0, 0) || grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) - DBUG_RETURN(TRUE); + { + res= TRUE; + goto err; + } for (sl= select_lex; sl; sl= sl->next_select()) { for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) @@ -247,7 +250,8 @@ bool mysql_create_view(THD *thd, { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->priv_user, thd->host_or_ip, tbl->table_name); - DBUG_RETURN(TRUE); + res= TRUE; + goto err; } /* Mark this table as a table which will be checked after the prepare @@ -306,7 +310,10 @@ bool mysql_create_view(THD *thd, #endif if (open_and_lock_tables(thd, tables)) - DBUG_RETURN(TRUE); + { + res= TRUE; + goto err; + } /* check that tables are not temporary and this VIEW do not used in query @@ -374,7 +381,10 @@ bool mysql_create_view(THD *thd, } if (check_duplicate_names(select_lex->item_list, 1)) - DBUG_RETURN(TRUE); + { + res= TRUE; + goto err; + } #ifndef NO_EMBEDDED_ACCESS_CHECKS /* @@ -404,7 +414,8 @@ bool mysql_create_view(THD *thd, my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "create view", thd->priv_user, thd->host_or_ip, item->name, view->table_name); - DBUG_RETURN(TRUE); + res= TRUE; + goto err; } } } From e80aa010874832d03196fbdcb66860a13bc0ecd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 23:53:12 +0400 Subject: [PATCH 10/80] Fix bug #11718 query with function, join and order by returns wrong type. create_tmp_field_from_item() was creating tmp field without regard to original field type of Item. This results in wrong type being reported to client. To create_tmp_field_from_item() added special handling for Items with DATE/TIME field types to preserve their type. sql/sql_select.cc: Fix bug #11718 query with function, join and order by returns wrong type. tests/mysql_client_test.c: Test case for bug #11718: query with function, join and order by returns wrong type --- sql/sql_select.cc | 10 +++++++++- tests/mysql_client_test.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9984cb4138f..73cfe153b9b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4899,7 +4899,15 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->name, table, item->unsigned_flag); break; case STRING_RESULT: - if (item->max_length > 255) + enum enum_field_types type; + /* + DATE/TIME fields have STRING_RESULT result type. To preserve + type they needed to be handled separately. + */ + if ((type= item->field_type()) == MYSQL_TYPE_DATETIME || + type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE) + new_field= item->tmp_table_field_from_field_type(table); + else if (item->max_length > 255) { if (convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 37d6d951f96..64c5e7edaf9 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11796,6 +11796,40 @@ static void test_bug12001() DIE_UNLESS(res==1); } +/* + Bug#11718: query with function, join and order by returns wrong type +*/ + +static void test_bug11718() +{ + MYSQL_RES *res; + int rc; + const char *query= "select str_to_date(concat(f3),'%Y%m%d') from t1,t2 " + "where f1=f2 order by f1"; + + myheader("test_bug11718"); + + rc= mysql_query(mysql, "drop table if exists t1, t2"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (f1 int)"); + myquery(rc); + rc= mysql_query(mysql, "create table t2 (f2 int, f3 numeric(8))"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1), (2)"); + myquery(rc); + rc= mysql_query(mysql, "insert into t2 values (1,20050101), (2,20050202)"); + myquery(rc); + rc= mysql_query(mysql, query); + myquery(rc); + res = mysql_store_result(mysql); + + if (!opt_silent) + printf("return type: %s", (res->fields[0].type == MYSQL_TYPE_DATE)?"DATE": + "not DATE"); + DIE_UNLESS(res->fields[0].type == MYSQL_TYPE_DATE); + rc= mysql_query(mysql, "drop table t1, t2"); + myquery(rc); +} /* Read and parse arguments and MySQL options from my.cnf */ @@ -12013,6 +12047,7 @@ static struct my_tests_st my_tests[]= { { "test_bug9735", test_bug9735 }, { "test_bug11183", test_bug11183 }, { "test_bug12001", test_bug12001 }, + { "test_bug11718", test_bug11718 }, { 0, 0 } }; From 31f0997b1a92479d01b464433c28ec7c4db6e310 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Aug 2005 23:47:03 +0200 Subject: [PATCH 11/80] mtr_process.pl: Longer shutdown timeout, slave may be in reconnect HUP seem to disturb exit(), added sleep to make sure output is flushed mysql-test/lib/mtr_process.pl: Longer shutdown timeout, slave may be in reconnect HUP seem to disturb exit(), added sleep to make sure output is flushed --- mysql-test/lib/mtr_process.pl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 1f18968031c..fb37296971e 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -331,7 +331,7 @@ sub mtr_kill_leftovers () { }); } - mtr_mysqladmin_shutdown(\@args); + mtr_mysqladmin_shutdown(\@args, 20); # We now have tried to terminate nice. We have waited for the listen # port to be free, but can't really tell if the mysqld process died @@ -441,7 +441,8 @@ sub mtr_stop_mysqld_servers ($) { # First try nice normal shutdown using 'mysqladmin' # ---------------------------------------------------------------------- - mtr_mysqladmin_shutdown($spec); + # Shutdown time must be high as slave may be in reconnect + mtr_mysqladmin_shutdown($spec, 70); # ---------------------------------------------------------------------- # We loop with waitpid() nonblocking to see how many of the ones we @@ -591,8 +592,9 @@ sub mtr_stop_mysqld_servers ($) { # ############################################################################## -sub mtr_mysqladmin_shutdown () { +sub mtr_mysqladmin_shutdown { my $spec= shift; + my $adm_shutdown_tmo= shift; my %mysql_admin_pids; my @to_kill_specs; @@ -631,7 +633,7 @@ sub mtr_mysqladmin_shutdown () { mtr_add_arg($args, "--protocol=tcp"); # Needed if no --socket } mtr_add_arg($args, "--connect_timeout=5"); - mtr_add_arg($args, "--shutdown_timeout=20"); + mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo"); mtr_add_arg($args, "shutdown"); # We don't wait for termination of mysqladmin my $pid= mtr_spawn($::exe_mysqladmin, $args, @@ -808,11 +810,15 @@ sub sleep_until_file_created ($$$) { # FIXME something is wrong, we sometimes terminate with "Hangup" written # to tty, and no STDERR output telling us why. +# FIXME for some readon, setting HUP to 'IGNORE' will cause exit() to +# write out "Hangup", and maybe loose some output. We insert a sleep... + sub mtr_exit ($) { my $code= shift; # cluck("Called mtr_exit()"); local $SIG{HUP} = 'IGNORE'; kill('HUP', -$$); + sleep 2; exit($code); } From 085c8d30425b60ee87ae25fd332b88eb1ba7d03b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 00:07:17 +0200 Subject: [PATCH 12/80] mtr_process.pl: Bug#11792: Create a shell like 'mysqltest' exit status mysql-test/lib/mtr_process.pl: Bug#11792: Create a shell like 'mysqltest' exit status --- mysql-test/lib/mtr_process.pl | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index fb37296971e..ec12bc3907c 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -185,10 +185,6 @@ sub spawn_parent_impl { if ( $mode eq 'run' or $mode eq 'test' ) { - my $exit_value= -1; -# my $signal_num= 0; -# my $dumped_core= 0; - if ( $mode eq 'run' ) { # Simple run of command, we wait for it to return @@ -199,12 +195,7 @@ sub spawn_parent_impl { mtr_error("$path ($pid) got lost somehow"); } - $exit_value= $?; -# $exit_value= $? >> 8; -# $signal_num= $? & 127; -# $dumped_core= $? & 128; - - return $exit_value; + return mtr_process_exit_status($?); } else { @@ -218,6 +209,7 @@ sub spawn_parent_impl { # FIXME is this as it should be? Can't mysqld terminate # normally from running a test case? + my $exit_value= -1; my $ret_pid; # What waitpid() returns while ( ($ret_pid= waitpid(-1,0)) != -1 ) @@ -230,10 +222,7 @@ sub spawn_parent_impl { if ( $ret_pid == $pid ) { # We got termination of mysqltest, we are done - $exit_value= $?; -# $exit_value= $? >> 8; -# $signal_num= $? & 127; -# $dumped_core= $? & 128; + $exit_value= mtr_process_exit_status($?); last; } @@ -292,6 +281,23 @@ sub spawn_parent_impl { } +# ---------------------------------------------------------------------- +# We try to emulate how an Unix shell calculates the exit code +# ---------------------------------------------------------------------- + +sub mtr_process_exit_status { + my $raw_status= shift; + + if ( $raw_status & 127 ) + { + return ($raw_status & 127) + 128; # Signal num + 128 + } + else + { + return $raw_status >> 8; # Exit code + } +} + ############################################################################## # From d1bdd18eb469dd0c731e2a3478e30da01d764afd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 00:16:44 +0200 Subject: [PATCH 13/80] mtr_timer.pl, mysql-test-run.pl, mtr_report.pl, mtr_process.pl: Added suite and test case timeout mtr_timer.pl: new file mysql-test/lib/mtr_process.pl: Added suite and test case timeout mysql-test/lib/mtr_report.pl: Added suite and test case timeout mysql-test/mysql-test-run.pl: Added suite and test case timeout mysql-test/lib/mtr_timer.pl: Added suite and test case timeout --- mysql-test/lib/mtr_process.pl | 21 +++++- mysql-test/lib/mtr_report.pl | 9 ++- mysql-test/lib/mtr_timer.pl | 127 ++++++++++++++++++++++++++++++++++ mysql-test/mysql-test-run.pl | 28 +++++++- 4 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 mysql-test/lib/mtr_timer.pl diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index ec12bc3907c..c9ae92305c2 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -210,6 +210,7 @@ sub spawn_parent_impl { # normally from running a test case? my $exit_value= -1; + my $saved_exit_value; my $ret_pid; # What waitpid() returns while ( ($ret_pid= waitpid(-1,0)) != -1 ) @@ -219,6 +220,24 @@ sub spawn_parent_impl { # but not $exit_value, this is flagged from # + my $timer_name= mtr_timer_timeout($::glob_timers, $ret_pid); + if ( $timer_name ) + { + if ( $timer_name eq "suite" ) + { + # We give up here + # FIXME we should only give up the suite, not all of the run? + print STDERR "\n"; + mtr_error("Test suite timeout"); + } + elsif ( $timer_name eq "testcase" ) + { + $saved_exit_value= 63; # Mark as timeout + kill(9, $pid); # Kill mysqltest + next; # Go on and catch the termination + } + } + if ( $ret_pid == $pid ) { # We got termination of mysqltest, we are done @@ -270,7 +289,7 @@ sub spawn_parent_impl { } } - return $exit_value; + return $saved_exit_value || $exit_value; } } else diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index b9dab6b8d32..5e1a8308505 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -109,7 +109,14 @@ sub mtr_report_test_failed ($) { my $tinfo= shift; $tinfo->{'result'}= 'MTR_RES_FAILED'; - print "[ fail ]\n"; + if ( $tinfo->{'timeout'} ) + { + print "[ fail ] timeout\n"; + } + else + { + print "[ fail ]\n"; + } # FIXME Instead of this test, and meaningless error message in 'else' # we should write out into $::path_timefile when the error occurs. diff --git a/mysql-test/lib/mtr_timer.pl b/mysql-test/lib/mtr_timer.pl new file mode 100644 index 00000000000..aab57d1bc52 --- /dev/null +++ b/mysql-test/lib/mtr_timer.pl @@ -0,0 +1,127 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use Carp qw(cluck); +use Socket; +use Errno; +use strict; + +#use POSIX ":sys_wait_h"; +use POSIX 'WNOHANG'; + +sub mtr_init_timers (); +sub mtr_timer_start($$$); +sub mtr_timer_stop($$); +sub mtr_timer_waitpid($$$); + +############################################################################## +# +# Initiate a structure shared by all timers +# +############################################################################## + +sub mtr_init_timers () { + my $timers = { timers => {}, pids => {}}; + return $timers; +} + + +############################################################################## +# +# Start, stop and poll a timer +# +# As alarm() isn't portable to Windows, we use separate processes to +# implement timers. That is why there is a mtr_timer_waitpid(), as this +# is where we catch a timeout. +# +############################################################################## + +sub mtr_timer_start($$$) { + my ($timers,$name,$duration)= @_; + + if ( exists $timers->{'timers'}->{$name} ) + { + # We have an old running timer, kill it + mtr_timer_stop($timers,$name); + } + + FORK: + { + my $tpid= fork(); + + if ( ! defined $tpid ) + { + if ( $! == $!{EAGAIN} ) # See "perldoc Errno" + { + mtr_debug("Got EAGAIN from fork(), sleep 1 second and redo"); + sleep(1); + redo FORK; + } + else + { + mtr_error("can't fork"); + } + } + + if ( $tpid ) + { + # Parent, record the information + $timers->{'timers'}->{$name}->{'pid'}= $tpid; + $timers->{'timers'}->{$name}->{'duration'}= $duration; + $timers->{'pids'}->{$tpid}= $name; + } + else + { + # Child, redirect output and exec + # FIXME do we need to redirect streams? + $0= "mtr_timer(timers,$name,$duration)"; + sleep($duration); + exit(0); + } + } +} + + +sub mtr_timer_stop ($$) { + my ($timers,$name)= @_; + + if ( exists $timers->{'timers'}->{$name} ) + { + my $tpid= $timers->{'timers'}->{$name}->{'pid'}; + + # FIXME as Cygwin reuses pids fast, maybe check that is + # the expected process somehow?! + kill(9, $tpid); + + # As the timers are so simple programs, we trust them to terminate, + # and use blocking wait for it. We wait just to avoid a zombie. + waitpid($tpid,0); + + delete $timers->{'timers'}->{$name}; # Remove the timer information + delete $timers->{'pids'}->{$tpid}; # and PID reference + + return 1; + } + else + { + mtr_debug("Asked to stop timer \"$name\" not started"); + return 0; + } +} + + +sub mtr_timer_timeout ($$) { + my ($timers,$pid)= @_; + + return "" unless exists $timers->{'pids'}->{$pid}; + + # We got a timeout + my $name= $timers->{'pids'}->{$pid}; + mtr_timer_stop($timers, $timers->{'timers'}->{$name}); + return $name; +} + +1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f3e42ecf755..456f481ce86 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -90,6 +90,7 @@ use strict; require "lib/mtr_cases.pl"; require "lib/mtr_process.pl"; +require "lib/mtr_timer.pl"; require "lib/mtr_io.pl"; require "lib/mtr_gcov.pl"; require "lib/mtr_gprof.pl"; @@ -137,6 +138,7 @@ our $glob_mysql_test_dir= undef; our $glob_mysql_bench_dir= undef; our $glob_hostname= undef; our $glob_scriptname= undef; +our $glob_timers= undef; our $glob_use_running_server= 0; our $glob_use_running_ndbcluster= 0; our $glob_use_embedded_server= 0; @@ -232,8 +234,10 @@ our $opt_skip_test; our $opt_sleep; our $opt_ps_protocol; -our $opt_sleep_time_after_restart= 1; +our $opt_sleep_time_after_restart= 1; our $opt_sleep_time_for_delete= 10; +our $opt_testcase_timeout= 5; # 5 min max +our $opt_suite_timeout= 120; # 2 hours max our $opt_socket; @@ -435,6 +439,8 @@ sub initial_setup () { $path_my_basedir= $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir; + + $glob_timers= mtr_init_timers(); } @@ -530,6 +536,8 @@ sub command_line_setup () { 'vardir=s' => \$opt_vardir, 'verbose' => \$opt_verbose, 'wait-timeout=i' => \$opt_wait_timeout, + 'testcase-timeout=i' => \$opt_testcase_timeout, + 'suite-timeout=i' => \$opt_suite_timeout, 'warnings|log-warnings' => \$opt_warnings, 'with-openssl' => \$opt_with_openssl, @@ -1197,6 +1205,8 @@ sub run_suite () { mtr_report("Finding Tests in the '$suite' suite"); + mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout); + my $tests= collect_test_cases($suite); mtr_report("Starting Tests in the '$suite' suite"); @@ -1205,7 +1215,9 @@ sub run_suite () { foreach my $tinfo ( @$tests ) { + mtr_timer_start($glob_timers,"testcase", 60 * $opt_testcase_timeout); run_testcase($tinfo); + mtr_timer_stop($glob_timers,"testcase"); } mtr_print_line(); @@ -1226,6 +1238,8 @@ sub run_suite () { } mtr_report_stats($tests); + + mtr_timer_stop($glob_timers,"suite"); } @@ -1523,6 +1537,11 @@ sub run_testcase ($) { # Testcase itself tell us to skip this one mtr_report_test_skipped($tinfo); } + elsif ( $res == 63 ) + { + $tinfo->{'timeout'}= 1; # Mark as timeout + report_failure_and_restart($tinfo); + } else { # Test case failed, if in control mysqltest returns 1 @@ -1657,8 +1676,6 @@ sub mysqld_arguments ($$$$$) { my $extra_opt= shift; my $slave_master_info= shift; -# print STDERR Dumper($extra_opt); - my $sidx= ""; # Index as string, 0 is empty string if ( $idx > 0 ) { @@ -2262,6 +2279,10 @@ Misc options help Get this help text unified-diff | udiff When presenting differences, use unified diff + testcase-timeout=MINUTES Max test case run time (default 5) + suite-timeout=MINUTES Max test suite run time (default 120) + + Options not yet described, or that I want to look into more big-test @@ -2281,4 +2302,5 @@ Options not yet described, or that I want to look into more HERE mtr_exit(1); + } From c7744c6df5c913f924fa02d0ec0ca6424105e336 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 14:02:25 +0200 Subject: [PATCH 14/80] bug#12118 - ndb alter table data loss Split table version into 2 (major, minor) Impl. signaling to API when table has been altered Allow running transactions to use any minor number for transactions mysql-test/r/ndb_alter_table.result: Allow running transactions to use old table definition when possible. mysql-test/t/ndb_alter_table.test: Allow running transactions to use old table definition when possible. ndb/include/kernel/BlockNumbers.h: remove GREP ndb/include/kernel/GlobalSignalNumbers.h: Add ALTER_TABL_REP and API_BROADCAST_REP ndb/include/kernel/kernel_types.h: table_version_major ndb/include/kernel/signaldata/AlterTable.hpp: New error code for alter table during rolling upgrade ndb/include/ndbapi/NdbDictionary.hpp: Add state on table object to represent an altered but still valid table object ndb/src/common/debugger/BlockNames.cpp: remove GREP ndb/src/common/util/version.c: Fix upgrades ndb/src/kernel/SimBlockList.cpp: remove GREP ndb/src/kernel/blocks/Makefile.am: remove GREP ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp: remove GREP ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Split tableSchemaVersion into 2 part 24 bit real version 8 bit for online alter table where old table definition is still usable ndb/src/kernel/blocks/dbdict/Dbdict.hpp: Check for same ndb versions ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp: Update schema printer ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: remove grep ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: 1) Use table_ version_major when checking table version 2) Dummy fix for BUG that tableSchemaVersion is only 16 bit in LQHKEYREQ ndb/src/kernel/blocks/dbtc/Dbtc.hpp: 1) Use table_ version_major when checking table version 2) Dummy fix for BUG that tableSchemaVersion is only 16 bit in LQHKEYREQ ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: 1) Use table_ version_major when checking table version 2) Dummy fix for BUG that tableSchemaVersion is only 16 bit in LQHKEYREQ ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp: remove GREP ndb/src/kernel/blocks/qmgr/Qmgr.hpp: Add support for sending REP to ALL api nodes ndb/src/kernel/blocks/qmgr/QmgrInit.cpp: Add support for sending REP to ALL api nodes ndb/src/kernel/blocks/qmgr/QmgrMain.cpp: Add support for sending REP to ALL api nodes ndb/src/kernel/blocks/suma/Suma.cpp: remove GREP ndb/src/mgmsrv/MgmtSrvr.cpp: remove GREP ndb/src/ndbapi/DictCache.cpp: Add support for alter_table_rep by setting status to Altered NOTE special handling of tables in state RETREIVING ndb/src/ndbapi/DictCache.hpp: Add support for alter_table_rep by setting status to Altered NOTE special handling of tables in state RETREIVING ndb/src/ndbapi/NdbDictionaryImpl.cpp: Change alter table so that remove from global cache is used wo/ retreiving it from there first as ALTER_TABLE_REP might already have changed the table object... ndb/src/ndbapi/TransporterFacade.cpp: Add support for ALTER_TABLE_REP sql/ha_ndbcluster.cc: Allow running transactions to use tables in state ALTERED...but new transactions may not... ndb/include/kernel/signaldata/ApiBroadcast.hpp: New BitKeeper file ``ndb/include/kernel/signaldata/ApiBroadcast.hpp'' --- mysql-test/r/ndb_alter_table.result | 18 +++- mysql-test/t/ndb_alter_table.test | 26 +++++- ndb/include/kernel/BlockNumbers.h | 4 +- ndb/include/kernel/GlobalSignalNumbers.h | 4 +- ndb/include/kernel/kernel_types.h | 7 ++ ndb/include/kernel/signaldata/AlterTable.hpp | 25 +++++- .../kernel/signaldata/ApiBroadcast.hpp | 31 +++++++ ndb/include/ndbapi/NdbDictionary.hpp | 5 +- ndb/src/common/debugger/BlockNames.cpp | 1 - ndb/src/common/util/version.c | 4 +- ndb/src/kernel/SimBlockList.cpp | 6 +- ndb/src/kernel/blocks/Makefile.am | 1 - ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp | 1 - ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 89 +++++++++++++++++-- ndb/src/kernel/blocks/dbdict/Dbdict.hpp | 1 + .../kernel/blocks/dbdict/printSchemaFile.cpp | 3 +- ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 2 - ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 7 +- ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 3 +- ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 4 +- ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 7 +- ndb/src/kernel/blocks/qmgr/Qmgr.hpp | 1 + ndb/src/kernel/blocks/qmgr/QmgrInit.cpp | 3 +- ndb/src/kernel/blocks/qmgr/QmgrMain.cpp | 38 +++++--- ndb/src/kernel/blocks/suma/Suma.cpp | 20 +---- ndb/src/mgmsrv/MgmtSrvr.cpp | 39 +------- ndb/src/ndbapi/DictCache.cpp | 72 ++++++++++++++- ndb/src/ndbapi/DictCache.hpp | 3 + ndb/src/ndbapi/NdbDictionaryImpl.cpp | 21 ++--- ndb/src/ndbapi/TransporterFacade.cpp | 12 +++ sql/ha_ndbcluster.cc | 5 +- 31 files changed, 339 insertions(+), 124 deletions(-) create mode 100644 ndb/include/kernel/signaldata/ApiBroadcast.hpp diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index 52ae0b58d56..63afc07718f 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -179,8 +179,24 @@ a b c 2 two two alter table t1 drop index c; select * from t1 where b = 'two'; -ERROR HY000: Table definition has changed, please retry transaction +a b c +2 two two select * from t1 where b = 'two'; a b c 2 two two drop table t1; +create table t3 (a int primary key) engine=ndbcluster; +begin; +insert into t3 values (1); +alter table t3 rename t4; +delete from t3; +insert into t3 values (1); +commit; +select * from t3; +ERROR HY000: Can't lock file (errno: 155) +select * from t4; +a +1 +drop table t4; +show tables; +Tables_in_test diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 9cc1426554f..e59183fcda1 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -144,7 +144,6 @@ select * from t1 where b = 'two'; connection server1; alter table t1 drop index c; connection server2; ---error 1105 select * from t1 where b = 'two'; select * from t1 where b = 'two'; connection server1; @@ -172,3 +171,28 @@ drop table t1; #truncate table t2; #select count(*) from t2; #drop table t2; + +connection server1; +create table t3 (a int primary key) engine=ndbcluster; + +connection server2; +begin; +insert into t3 values (1); + +connection server1; +alter table t3 rename t4; + +connection server2; +# This should work as transaction is ongoing... +delete from t3; +insert into t3 values (1); +commit; + +# This should fail as its a new transaction +--error 1015 +select * from t3; +select * from t4; +drop table t4; +show tables; +connection server1; + diff --git a/ndb/include/kernel/BlockNumbers.h b/ndb/include/kernel/BlockNumbers.h index cb3cc697eee..49b5842ac4e 100644 --- a/ndb/include/kernel/BlockNumbers.h +++ b/ndb/include/kernel/BlockNumbers.h @@ -44,8 +44,7 @@ #define TRIX 0xFF #define DBUTIL 0x100 #define SUMA 0x101 -#define GREP 0x102 -#define DBTUX 0x103 +#define DBTUX 0x102 const BlockReference BACKUP_REF = numberToRef(BACKUP, 0); const BlockReference DBTC_REF = numberToRef(DBTC, 0); @@ -61,7 +60,6 @@ const BlockReference CMVMI_REF = numberToRef(CMVMI, 0); const BlockReference TRIX_REF = numberToRef(TRIX, 0); const BlockReference DBUTIL_REF = numberToRef(DBUTIL, 0); const BlockReference SUMA_REF = numberToRef(SUMA, 0); -const BlockReference GREP_REF = numberToRef(GREP, 0); const BlockReference DBTUX_REF = numberToRef(DBTUX, 0); const BlockNumber MIN_BLOCK_NO = BACKUP; diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h index 9413f4ef56a..ff3690d60a5 100644 --- a/ndb/include/kernel/GlobalSignalNumbers.h +++ b/ndb/include/kernel/GlobalSignalNumbers.h @@ -777,8 +777,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; /** * Grep signals */ -#define GSN_GREP_SUB_CREATE_REQ 606 -#define GSN_GREP_SUB_CREATE_REF 607 +#define GSN_ALTER_TABLE_REP 606 +#define GSN_API_BROADCAST_REP 607 #define GSN_GREP_SUB_CREATE_CONF 608 #define GSN_GREP_CREATE_REQ 609 #define GSN_GREP_CREATE_REF 610 diff --git a/ndb/include/kernel/kernel_types.h b/ndb/include/kernel/kernel_types.h index b176d20798c..e16e61471e7 100644 --- a/ndb/include/kernel/kernel_types.h +++ b/ndb/include/kernel/kernel_types.h @@ -36,6 +36,13 @@ enum Operation_t { #endif }; +inline +Uint32 +table_version_major(Uint32 ver) +{ + return ver & 0x00FFFFFF; +} + #endif diff --git a/ndb/include/kernel/signaldata/AlterTable.hpp b/ndb/include/kernel/signaldata/AlterTable.hpp index 173a9acf9ed..16c9eb204c9 100644 --- a/ndb/include/kernel/signaldata/AlterTable.hpp +++ b/ndb/include/kernel/signaldata/AlterTable.hpp @@ -129,7 +129,8 @@ public: InvalidPrimaryKeySize = 739, NullablePrimaryKey = 740, UnsupportedChange = 741, - BackupInProgress = 762 + BackupInProgress = 762, + IncompatibleVersions = 763 }; private: @@ -177,4 +178,26 @@ private: Uint32 tableVersion; }; +/** + * Inform API about change of table definition + */ +struct AlterTableRep +{ + friend bool printALTER_TABLE_REP(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 3 ); + + enum Change_type + { + CT_ALTERED = 0x1, + CT_DROPPED = 0x2 + }; + + Uint32 tableId; + Uint32 tableVersion; + Uint32 changeType; + + SECTION( TABLE_NAME = 0 ); +}; + #endif diff --git a/ndb/include/kernel/signaldata/ApiBroadcast.hpp b/ndb/include/kernel/signaldata/ApiBroadcast.hpp new file mode 100644 index 00000000000..8050326ce78 --- /dev/null +++ b/ndb/include/kernel/signaldata/ApiBroadcast.hpp @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef API_BROADCAST_HPP +#define API_BROADCAST_HPP + +#include "SignalData.hpp" + +struct ApiBroadcastRep +{ + STATIC_CONST( SignalLength = 2 ); + + Uint32 gsn; + Uint32 minVersion; + Uint32 theData[1]; +}; + +#endif diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index 85615f3aa66..a541cd5190e 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -77,9 +77,10 @@ public: ///< changes to take effect Retrieved, ///< The object exist and has been read ///< into main memory from NDB Kernel - Invalid ///< The object has been invalidated + Invalid, ///< The object has been invalidated ///< and should not be used - + Altered ///< Table has been altered in NDB kernel + ///< but is still valid for usage }; /** diff --git a/ndb/src/common/debugger/BlockNames.cpp b/ndb/src/common/debugger/BlockNames.cpp index 44650b84c5c..0c61b6327ef 100644 --- a/ndb/src/common/debugger/BlockNames.cpp +++ b/ndb/src/common/debugger/BlockNames.cpp @@ -32,7 +32,6 @@ const BlockName BlockNames[] = { { "BACKUP", BACKUP }, { "DBUTIL", DBUTIL }, { "SUMA", SUMA }, - { "GREP", GREP }, { "DBTUX", DBTUX } }; diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c index 7221dc48fa4..05ce6d88d11 100644 --- a/ndb/src/common/util/version.c +++ b/ndb/src/common/util/version.c @@ -90,7 +90,8 @@ void ndbSetOwnVersion() {} #ifndef TEST_VERSION struct NdbUpGradeCompatible ndbCompatibleTable_full[] = { - { MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,10), UG_Range }, + { MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,15), UG_Range }, + { MAKE_VERSION(4,1,14), MAKE_VERSION(4,1,10), UG_Range }, { MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact }, { MAKE_VERSION(4,1,9), MAKE_VERSION(4,1,8), UG_Exact }, { MAKE_VERSION(3,5,2), MAKE_VERSION(3,5,1), UG_Exact }, @@ -98,6 +99,7 @@ struct NdbUpGradeCompatible ndbCompatibleTable_full[] = { }; struct NdbUpGradeCompatible ndbCompatibleTable_upgrade[] = { + { MAKE_VERSION(4,1,15), MAKE_VERSION(4,1,14), UG_Exact }, { MAKE_VERSION(3,5,4), MAKE_VERSION(3,5,3), UG_Exact }, { 0, 0, UG_Null } }; diff --git a/ndb/src/kernel/SimBlockList.cpp b/ndb/src/kernel/SimBlockList.cpp index bf3958cf137..6029fc7e225 100644 --- a/ndb/src/kernel/SimBlockList.cpp +++ b/ndb/src/kernel/SimBlockList.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -97,13 +96,14 @@ SimBlockList::load(const Configuration & conf){ theList[11] = NEW_BLOCK(Backup)(conf); theList[12] = NEW_BLOCK(DbUtil)(conf); theList[13] = NEW_BLOCK(Suma)(conf); - theList[14] = NEW_BLOCK(Grep)(conf); + theList[14] = 0; //NEW_BLOCK(Grep)(conf); theList[15] = NEW_BLOCK(Dbtux)(conf); // Metadata common part shared by block instances ptrMetaDataCommon = new MetaData::Common(*dbdict, *dbdih); for (int i = 0; i < noOfBlocks; i++) - theList[i]->setMetaDataCommon(ptrMetaDataCommon); + if(theList[i]) + theList[i]->setMetaDataCommon(ptrMetaDataCommon); } void diff --git a/ndb/src/kernel/blocks/Makefile.am b/ndb/src/kernel/blocks/Makefile.am index 7ee90e6239f..8addf257003 100644 --- a/ndb/src/kernel/blocks/Makefile.am +++ b/ndb/src/kernel/blocks/Makefile.am @@ -13,7 +13,6 @@ SUBDIRS = \ backup \ dbutil \ suma \ - grep \ dbtux windoze-dsp: diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index 0274ef4af3e..7659ee1145d 100644 --- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -987,7 +987,6 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); sendSignal(DBUTIL_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); sendSignal(SUMA_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); - sendSignal(GREP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); sendSignal(TRIX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); sendSignal(DBTUX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB); diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index a3ea195786e..f60720a1345 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -77,6 +77,7 @@ #include #include #include +#include #define ZNOT_FOUND 626 #define ZALREADYEXIST 630 @@ -91,6 +92,27 @@ #define DIV(x,y) (((x)+(y)-1)/(y)) #include +static +Uint32 +alter_table_inc_schema_version(Uint32 old) +{ + return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000); +} + +static +Uint32 +alter_table_dec_schema_version(Uint32 old) +{ + return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000); +} + +static +Uint32 +create_table_inc_schema_version(Uint32 old) +{ + return (old + 0x00000001) & 0x00FFFFFF; +} + /* **************************************************************** */ /* ---------------------------------------------------------------- */ /* MODULE: GENERAL MODULE -------------------------------- */ @@ -584,7 +606,7 @@ void Dbdict::openTableFile(Signal* signal, jam(); fsOpenReq->fileFlags = FsOpenReq::OM_READONLY; }//if - ndbrequire(tablePtr.p->tableVersion < ZNIL); + fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes FsOpenReq::setVersion(fsOpenReq->fileNumber, 1); FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST); @@ -776,7 +798,7 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId, case SchemaFile::ADD_STARTED: jam(); ok = true; - ndbrequire((oldVersion + 1) == newVersion); + ndbrequire(create_table_inc_schema_version(oldVersion) == newVersion); ndbrequire(oldState == SchemaFile::INIT || oldState == SchemaFile::DROP_TABLE_COMMITTED); break; @@ -789,7 +811,7 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId, case SchemaFile::ALTER_TABLE_COMMITTED: jam(); ok = true; - ndbrequire((oldVersion + 1) == newVersion); + ndbrequire(alter_table_inc_schema_version(oldVersion) == newVersion); ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED || oldState == SchemaFile::ALTER_TABLE_COMMITTED); break; @@ -2806,6 +2828,21 @@ Dbdict::execBACKUP_FRAGMENT_REQ(Signal* signal) } } +bool +Dbdict::check_ndb_versions() const +{ + Uint32 node = 0; + Uint32 version = getNodeInfo(getOwnNodeId()).m_version; + while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound) + { + if(getNodeInfo(node).m_version != version) + { + return false; + } + } + return true; +} + void Dbdict::execALTER_TABLE_REQ(Signal* signal) { @@ -2842,6 +2879,13 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) alterTableRef(signal, req, AlterTableRef::Busy); return; } + + if (!check_ndb_versions()) + { + jam(); + alterTableRef(signal, req, AlterTableRef::IncompatibleVersions); + return; + } const TableRecord::TabState tabState = tablePtr.p->tabState; bool ok = false; @@ -2992,7 +3036,7 @@ Dbdict::alterTable_backup_mutex_locked(Signal* signal, lreq->clientData = alterTabPtr.p->m_senderData; lreq->changeMask = alterTabPtr.p->m_changeMask; lreq->tableId = tablePtr.p->tableId; - lreq->tableVersion = tablePtr.p->tableVersion + 1; + lreq->tableVersion = alter_table_inc_schema_version(tablePtr.p->tableVersion); lreq->gci = tablePtr.p->gciTableCreated; lreq->requestType = AlterTabReq::AlterTablePrepare; @@ -3072,6 +3116,14 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) alterTabRef(signal, req, AlterTableRef::Busy); return; } + + if (!check_ndb_versions()) + { + jam(); + alterTabRef(signal, req, AlterTableRef::IncompatibleVersions); + return; + } + alterTabPtr.p->m_alterTableId = tableId; alterTabPtr.p->m_coordinatorRef = senderRef; @@ -3114,7 +3166,7 @@ Dbdict::execALTER_TAB_REQ(Signal * signal) } ndbrequire(ok); - if(tablePtr.p->tableVersion + 1 != tableVersion){ + if(alter_table_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){ jam(); alterTabRef(signal, req, AlterTableRef::InvalidTableVersion); return; @@ -3599,7 +3651,7 @@ void Dbdict::revertAlterTable(Signal * signal, // Restore name strcpy(tablePtr.p->tableName, alterTabPtrP->previousTableName); // Revert schema version - tablePtr.p->tableVersion = tablePtr.p->tableVersion - 1; + tablePtr.p->tableVersion = alter_table_dec_schema_version(tablePtr.p->tableVersion); // Put it back #ifdef VM_TRACE ndbrequire(!c_tableRecordHash.find(tmp, * tablePtr.p)); @@ -3659,6 +3711,27 @@ Dbdict::alterTab_writeTableConf(Signal* signal, conf->requestType = AlterTabReq::AlterTableCommit; sendSignal(coordinatorRef, GSN_ALTER_TAB_CONF, signal, AlterTabConf::SignalLength, JBB); + + + { + ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend(); + api->gsn = GSN_ALTER_TABLE_REP; + api->minVersion = MAKE_VERSION(4,1,15); + + AlterTableRep* rep = (AlterTableRep*)api->theData; + rep->tableId = tabPtr.p->tableId; + rep->tableVersion = alter_table_dec_schema_version(tabPtr.p->tableVersion); + rep->changeType = AlterTableRep::CT_ALTERED; + + LinearSectionPtr ptr[3]; + ptr[0].p = (Uint32*)alterTabPtr.p->previousTableName; + ptr[0].sz = (sizeof(alterTabPtr.p->previousTableName) + 3) >> 2; + + sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal, + ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength, + JBB, ptr,1); + } + if(coordinatorRef != reference()) { jam(); // Release resources @@ -3711,7 +3784,7 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){ c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage); SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i); - tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1; + tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion); /** * Pack @@ -3740,7 +3813,7 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){ req->gci = 0; req->tableId = tabPtr.i; - req->tableVersion = tabEntry->m_tableVersion + 1; + req->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion); sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal, CreateTabReq::SignalLength, JBB); diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 48dc2d2c2d5..77a44d0ad24 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -578,6 +578,7 @@ private: void execALTER_TAB_REQ(Signal* signal); void execALTER_TAB_REF(Signal* signal); void execALTER_TAB_CONF(Signal* signal); + bool check_ndb_versions() const; /* * 2.4 COMMON STORED VARIABLES diff --git a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp index 0ba52878b7c..3e944485e1c 100644 --- a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp +++ b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp @@ -58,7 +58,8 @@ print(const char * filename, const SchemaFile * file){ SchemaFile::TableEntry te = file->TableEntries[i]; if(te.m_tableState != SchemaFile::INIT){ ndbout << "Table " << i << ": State = " << te.m_tableState - << " version = " << te.m_tableVersion + << " version = " << table_version_major(te.m_tableVersion) << + << "(" << table_version_minor(te.m_tableVersion) << ")" << " type = " << te.m_tableType << " noOfPages = " << te.m_noOfPages << " gcp: " << te.m_gcp << endl; diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 82678827927..94426c8be3f 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1886,8 +1886,6 @@ void Dbdih::execINCL_NODECONF(Signal* signal) // Suma will not send response to this for now, later... sendSignal(SUMA_REF, GSN_INCL_NODEREQ, signal, 2, JBB); - // Grep will not send response to this for now, later... - sendSignal(GREP_REF, GSN_INCL_NODEREQ, signal, 2, JBB); return; }//if if (TstartNode_or_blockref == numberToRef(BACKUP, getOwnNodeId())){ diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 5d689274f26..05d76f5fb25 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3512,7 +3512,8 @@ void Dblqh::execLQHKEYREQ(Signal* signal) LQHKEY_abort(signal, 4); return; } - if(tabptr.p->schemaVersion != schemaVersion){ + if(table_version_major(tabptr.p->schemaVersion) != + table_version_major(schemaVersion)){ LQHKEY_abort(signal, 5); return; } @@ -4451,7 +4452,7 @@ void Dblqh::packLqhkeyreqLab(Signal* signal) lqhKeyReq->requestInfo = Treqinfo; lqhKeyReq->tcBlockref = sig4; - sig0 = regTcPtr->tableref + (regTcPtr->schemaVersion << 16); + sig0 = regTcPtr->tableref + ((regTcPtr->schemaVersion << 16) & 0xFFFF0000); sig1 = regTcPtr->fragmentid + (regTcPtr->nodeAfterNext[0] << 16); sig2 = regTcPtr->transid[0]; sig3 = regTcPtr->transid[1]; @@ -15840,7 +15841,7 @@ Uint32 Dblqh::checkIfExecLog(Signal* signal) tabptr.i = tcConnectptr.p->tableref; ptrCheckGuard(tabptr, ctabrecFileSize, tablerec); if (getFragmentrec(signal, tcConnectptr.p->fragmentid) && - (tabptr.p->schemaVersion == tcConnectptr.p->schemaVersion)) { + (table_version_major(tabptr.p->schemaVersion) == table_version_major(tcConnectptr.p->schemaVersion))) { if (fragptr.p->execSrStatus != Fragrecord::IDLE) { if (fragptr.p->execSrNoReplicas > logPartPtr.p->execSrExecuteIndex) { ndbrequire((fragptr.p->execSrNoReplicas - 1) < 4); diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index fbd181cae24..61afef30b43 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -958,7 +958,8 @@ public: Uint8 storedTable; bool checkTable(Uint32 schemaVersion) const { - return enabled && !dropping && (schemaVersion == currentSchemaVersion); + return enabled && !dropping && + (table_version_major(schemaVersion) == table_version_major(currentSchemaVersion)); } Uint32 getErrorCode(Uint32 schemaVersion) const; diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 736a660f396..93b122b9a99 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -3196,7 +3196,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal, lqhKeyReq->tcBlockref = sig4; lqhKeyReq->savePointId = sig5; - sig0 = regCachePtr->tableref + (regCachePtr->schemaVersion << 16); + sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000); sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16); sig2 = regApiPtr->transid[0]; sig3 = regApiPtr->transid[1]; @@ -12877,7 +12877,7 @@ Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const { return ZNO_SUCH_TABLE; if(dropping) return ZDROP_TABLE_IN_PROGRESS; - if(schemaVersion != currentSchemaVersion) + if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion)) return ZWRONG_SCHEMA_VERSION_ERROR; ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode", __FILE__, __LINE__); diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 9eaa203b098..c80891548cf 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -76,7 +76,6 @@ static BlockInfo ALL_BLOCKS[] = { { BACKUP_REF, 1 , 10000, 10999 }, { DBUTIL_REF, 1 , 11000, 11999 }, { SUMA_REF, 1 , 13000, 13999 }, - { GREP_REF, 1 , 0, 0 }, { DBTUX_REF, 1 , 12000, 12999 } }; @@ -1453,9 +1452,6 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal) sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - sendSignal(GREP_REF, GSN_NODE_FAILREP, signal, - NodeFailRep::SignalLength, JBB); - Uint32 nodeId = 0; while(!allFailed.isclear()){ nodeId = allFailed.find(nodeId + 1); @@ -2381,7 +2377,6 @@ void Ndbcntr::execREAD_CONFIG_CONF(Signal* signal){ void Ndbcntr::execSTART_ORD(Signal* signal){ jamEntry(); - ndbrequire(NO_OF_BLOCKS == ALL_BLOCKS_SZ); c_missra.execSTART_ORD(signal); } @@ -2456,7 +2451,7 @@ void Ndbcntr::Missra::sendNextREAD_CONFIG_REQ(Signal* signal){ * Finished... */ currentStartPhase = 0; - for(Uint32 i = 0; i #include #include +#include #include @@ -1702,16 +1703,6 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA); - /** - * GREP also need the information that an API node - * (actually a REP node) has failed. - * - * GREP does however NOT send a CONF on this signal, i.e. - * the API_FAILREQ signal to GREP is like a REP signal - * (i.e. without any confirmation). - */ - sendSignal(GREP_REF, GSN_API_FAILREQ, signal, 2, JBA); - /**------------------------------------------------------------------------- * THE OTHER NODE WAS AN API NODE. THE COMMUNICATION LINK IS ALREADY * BROKEN AND THUS NO ACTION IS NEEDED TO BREAK THE CONNECTION. @@ -3926,3 +3917,30 @@ void Qmgr::execSET_VAR_REQ(Signal* signal) }// switch #endif }//execSET_VAR_REQ() + +void +Qmgr::execAPI_BROADCAST_REP(Signal* signal) +{ + jamEntry(); + ApiBroadcastRep api= *(const ApiBroadcastRep*)signal->getDataPtr(); + + Uint32 len = signal->getLength() - ApiBroadcastRep::SignalLength; + memmove(signal->theData, signal->theData+ApiBroadcastRep::SignalLength, + 4*len); + + NodeBitmask mask; + NodeRecPtr nodePtr; + for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) + { + jam(); + ptrAss(nodePtr, nodeRec); + if (nodePtr.p->phase == ZAPI_ACTIVE && + getNodeInfo(nodePtr.i).m_version >= api.minVersion) + { + mask.set(nodePtr.i); + } + } + + NodeReceiverGroup rg(API_CLUSTERMGR, mask); + sendSignal(rg, api.gsn, signal, len, JBB); // forward sections +} diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp index 44ac054dd67..84a59f440d9 100644 --- a/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/ndb/src/kernel/blocks/suma/Suma.cpp @@ -2143,7 +2143,8 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){ case SubCreateReq::DatabaseSnapshot: case SubCreateReq::SelectiveTableSnapshot: jam(); - subbPtr.p->m_subscriberRef = GREP_REF; + ndbrequire(false); + //subbPtr.p->m_subscriberRef = GREP_REF; subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData; break; case SubCreateReq::SingleTableScan: @@ -2971,16 +2972,6 @@ SumaParticipant::execSUB_GCP_COMPLETE_REP(Signal* signal){ Uint32 gci = rep->gci; c_lastCompleteGCI = gci; - /** - * always send SUB_GCP_COMPLETE_REP to Grep (so - * Lars can do funky stuff calculating intervals, - * even before the subscription is started - */ - rep->senderRef = reference(); - rep->senderData = 0; //ignored in grep - EXECUTE_DIRECT(refToBlock(GREP_REF), GSN_SUB_GCP_COMPLETE_REP, signal, - SubGcpCompleteRep::SignalLength); - /** * Signal to subscriber(s) */ @@ -3005,13 +2996,6 @@ SumaParticipant::execSUB_GCP_COMPLETE_REP(Signal* signal){ ndbout_c("GSN_SUB_GCP_COMPLETE_REP to %s:", getBlockName(refToBlock(ref))); #else - /** - * Ignore sending to GREP (since we sent earlier) - */ - if (ref == GREP_REF) { - jam(); - continue; - } CRASH_INSERTION(13018); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index ceaedc9955b..292e13a234b 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -2541,44 +2541,7 @@ MgmtSrvr::backupCallback(BackupEvent & event) int MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted) { - bool next; - NodeId nodeId = 0; - - while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true && - theFacade->get_node_alive(nodeId) == false); - - if(!next){ - return NO_CONTACT_WITH_DB_NODES; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - GrepReq* req = CAST_PTR(GrepReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, GREP, GSN_GREP_REQ, GrepReq::SignalLength); - req->senderRef = _ownReference; - req->request = request; - - int result; - if (waitCompleted) - result = sendRecSignal(nodeId, NO_WAIT, signal, true); - else - result = sendRecSignal(nodeId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - /** - * @todo - * Maybe add that we should receive a confirmation that the - * request was received ok. - * Then we should give the user the correct repReqId. - */ - - *repReqId = 4711; - + abort(); return 0; } diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index ccc45a04824..ca361e900b1 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -21,6 +21,9 @@ #include #include +static NdbTableImpl f_invalid_table; +static NdbTableImpl f_altered_table; + Ndb_local_table_info * Ndb_local_table_info::create(NdbTableImpl *table_impl, Uint32 sz) { @@ -164,21 +167,41 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab) TableVersion & ver = vers->back(); if(ver.m_status != RETREIVING || - ver.m_impl != 0 || + !(ver.m_impl == 0 || + ver.m_impl == &f_invalid_table || ver.m_impl == &f_altered_table) || ver.m_version != 0 || ver.m_refCount == 0){ abort(); } - if(tab == 0){ + if(tab == 0) + { // No table found in db vers->erase(sz - 1); - } else { + } + else if (ver.m_impl == 0) { ver.m_impl = tab; ver.m_version = tab->m_version; ver.m_status = OK; + } + else if (ver.m_impl == &f_invalid_table) + { + ver.m_impl = tab; + ver.m_version = tab->m_version; + ver.m_status = DROPPED; + ver.m_impl->m_status = NdbDictionary::Object::Invalid; + } + else if(ver.m_impl == &f_altered_table) + { + ver.m_impl = tab; + ver.m_version = tab->m_version; + ver.m_status = DROPPED; + ver.m_impl->m_status = NdbDictionary::Object::Altered; + } + else + { + abort(); } - NdbCondition_Broadcast(m_waitForTableCondition); return tab; } @@ -275,4 +298,45 @@ GlobalDictCache::release(NdbTableImpl * tab){ abort(); } +void +GlobalDictCache::alter_table_rep(const char * name, + Uint32 tableId, + Uint32 tableVersion, + bool altered) +{ + const Uint32 len = strlen(name); + Vector * vers = + m_tableHash.getData(name, len); + + if(vers == 0) + { + return; + } + + const Uint32 sz = vers->size(); + if(sz == 0) + { + return; + } + + for(Uint32 i = 0; i < sz; i++) + { + TableVersion & ver = (* vers)[i]; + if(ver.m_version == tableVersion && ver.m_impl && + ver.m_impl->m_tableId == tableId) + { + ver.m_status = DROPPED; + ver.m_impl->m_status = altered ? + NdbDictionary::Object::Altered : NdbDictionary::Object::Invalid; + return; + } + + if(i == sz - 1 && ver.m_status == RETREIVING) + { + ver.m_impl = altered ? &f_altered_table : &f_invalid_table; + return; + } + } +} + template class Vector; diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp index ca31c345396..7f2ee457476 100644 --- a/ndb/src/ndbapi/DictCache.hpp +++ b/ndb/src/ndbapi/DictCache.hpp @@ -68,6 +68,9 @@ public: NdbTableImpl* put(const char * name, NdbTableImpl *); void drop(NdbTableImpl *); void release(NdbTableImpl *); + + void alter_table_rep(const char * name, + Uint32 tableId, Uint32 tableVersion, bool altered); public: enum Status { OK = 0, diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 27fd70cd0f4..8b1847502d9 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1439,25 +1439,22 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl) const char * originalExternalName = externalName.c_str(); DBUG_ENTER("NdbDictionaryImpl::alterTable"); - if(!get_local_table_info(originalInternalName, false)){ + Ndb_local_table_info * local = 0; + if((local= get_local_table_info(originalInternalName, false)) == 0) + { m_error.code = 709; DBUG_RETURN(-1); } + // Alter the table int ret = m_receiver.alterTable(m_ndb, impl); if(ret == 0){ // Remove cached information and let it be refreshed at next access - if (m_localHash.get(originalInternalName) != NULL) { - m_localHash.drop(originalInternalName); - m_globalHash->lock(); - NdbTableImpl * cachedImpl = m_globalHash->get(originalInternalName); - // If in local cache it must be in global - if (!cachedImpl) - abort(); - cachedImpl->m_status = NdbDictionary::Object::Invalid; - m_globalHash->drop(cachedImpl); - m_globalHash->unlock(); - } + m_globalHash->lock(); + local->m_table_impl->m_status = NdbDictionary::Object::Invalid; + m_globalHash->drop(local->m_table_impl); + m_globalHash->unlock(); + m_localHash.drop(originalInternalName); } DBUG_RETURN(ret); } diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp index 93cec59ada6..a89b6287872 100644 --- a/ndb/src/ndbapi/TransporterFacade.cpp +++ b/ndb/src/ndbapi/TransporterFacade.cpp @@ -35,6 +35,7 @@ #include #include #include +#include //#define REPORT_TRANSPORTER //#define API_TRACE; @@ -305,6 +306,17 @@ execute(void * callbackObj, SignalHeader * const header, theFacade->theArbitMgr->doStop(theData); break; + case GSN_ALTER_TABLE_REP: + { + const AlterTableRep* rep = (const AlterTableRep*)theData; + theFacade->m_globalDictCache.lock(); + theFacade->m_globalDictCache. + alter_table_rep((const char*)ptr[0].p, + rep->tableId, + rep->tableVersion, + rep->changeType == AlterTableRep::CT_ALTERED); + theFacade->m_globalDictCache.unlock(); + } default: break; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 65c5fcb7de4..533895ce378 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3266,7 +3266,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); // Check if thread has stale local cache - if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) + // New transaction must not use old tables... (trans != 0) + // Running might... + if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved) + || tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); if (!(tab= dict->getTable(m_tabname, &tab_info))) From b1921c85ba5e1892af48df31ad38a89f65989012 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 19:07:23 +0400 Subject: [PATCH 15/80] Fix for bug #11896 "Partial locking in case of recursive trigger definitions". If we are in stored function or trigger we should ensure that we won't change table that is already used by calling statement (this can damage table or easily cause infinite loops). Particularly this means that recursive triggers should be disallowed. mysql-test/r/sp-error.result: Added tests checking that in functions we don't allow to update tables which are used by statements which invoke these functions. mysql-test/r/trigger.result: Added test for bug #11896 "Partial locking in case of recursive trigger definitions". mysql-test/t/sp-error.test: Added tests checking that in functions we don't allow to update tables which are used by statements which invoke these functions. mysql-test/t/trigger.test: Added test for bug #11896 "Partial locking in case of recursive trigger definitions". sql/share/errmsg.txt: Added error messages for complaining about situations when in function or trigger we try to change table which is used in statement invoking this function or trigger. sql/sql_base.cc: open_table(): If we are in stored function or trigger we should ensure that we won't change table that is already used by calling statement (this can damage table or easily cause infinite loops). So if we are opening table for writing, we should check that it is not already open by some calling stamement. --- mysql-test/r/sp-error.result | 30 +++++++++++++++ mysql-test/r/trigger.result | 41 ++++++++++++++++++++ mysql-test/t/sp-error.test | 29 ++++++++++++++ mysql-test/t/trigger.test | 36 ++++++++++++++++++ sql/share/errmsg.txt | 2 + sql/sql_base.cc | 74 ++++++++++++++++++++++++------------ 6 files changed, 188 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index bd383379abc..4ac29a07757 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -299,6 +299,36 @@ lock tables t1 read, mysql.proc read| unlock tables| lock tables mysql.proc write| unlock tables| +drop function if exists f1| +create function f1(i int) returns int +begin +insert into t1 (val) values (i); +return 0; +end| +select val, f1(val) from t1| +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select val, f1(val) from t1 as tab| +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select * from t1| +val x +42 3.1 +19 1.2 +update t1 set val= f1(val)| +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select * from t1| +val x +42 3.1 +19 1.2 +select f1(17)| +f1(17) +0 +select * from t1| +val x +42 3.1 +19 1.2 +17 NULL +delete from t1 where val= 17| +drop function f1| create procedure bug1965() begin declare c cursor for select val from t1 order by valname; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index ee0a6f6b744..7e359d3703e 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -664,3 +664,44 @@ end| update t1 set data = 1; update t1 set data = 2; drop table t1; +create table t1 (f1 integer); +create table t2 (f2 integer); +create trigger t1_ai after insert on t1 +for each row insert into t2 values (new.f1+1); +create trigger t2_ai after insert on t2 +for each row insert into t1 values (new.f2+1); +insert into t1 values (1); +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select * from t1; +f1 +1 +select * from t2; +f2 +2 +drop trigger t1_ai; +drop trigger t2_ai; +create trigger t1_bu before update on t1 +for each row insert into t1 values (2); +update t1 set f1= 10; +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select * from t1; +f1 +1 +drop trigger t1_bu; +create trigger t1_bu before update on t1 +for each row delete from t1 where f1=new.f1; +update t1 set f1= 10; +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +select * from t1; +f1 +1 +drop trigger t1_bu; +create trigger t1_bi before insert on t1 +for each row set new.f1=(select sum(f1) from t1); +insert into t1 values (3); +select * from t1; +f1 +1 +1 +drop trigger t1_bi; +drop tables t1, t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 349bd148814..b9abdb1b74a 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -409,6 +409,35 @@ lock tables mysql.proc write| unlock tables| +# +# Check that in functions we don't allow to update tables which +# are used by statements which invoke these functions. +# +--disable_warnings +drop function if exists f1| +--enable_warnings +create function f1(i int) returns int +begin + insert into t1 (val) values (i); + return 0; +end| +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +select val, f1(val) from t1| +# Table alias should not matter +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +select val, f1(val) from t1 as tab| +select * from t1| +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +update t1 set val= f1(val)| +select * from t1| +# But this should be OK +select f1(17)| +select * from t1| +# Cleanup +delete from t1 where val= 17| +drop function f1| + + # # BUG#1965 # diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 49ec42568ad..62f14941579 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -685,3 +685,39 @@ update t1 set data = 2; connection default; drop table t1; + +# Test for bug #11896 "Partial locking in case of recursive trigger +# definitions". Recursion in triggers should not be allowed. +# We also should not allow to change tables which are used in +# statements invoking this trigger. +create table t1 (f1 integer); +create table t2 (f2 integer); +create trigger t1_ai after insert on t1 + for each row insert into t2 values (new.f1+1); +create trigger t2_ai after insert on t2 + for each row insert into t1 values (new.f2+1); +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +insert into t1 values (1); +select * from t1; +select * from t2; +drop trigger t1_ai; +drop trigger t2_ai; +create trigger t1_bu before update on t1 + for each row insert into t1 values (2); +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +update t1 set f1= 10; +select * from t1; +drop trigger t1_bu; +create trigger t1_bu before update on t1 + for each row delete from t1 where f1=new.f1; +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +update t1 set f1= 10; +select * from t1; +drop trigger t1_bu; +# This should work tough +create trigger t1_bi before insert on t1 + for each row set new.f1=(select sum(f1) from t1); +insert into t1 values (3); +select * from t1; +drop trigger t1_bi; +drop tables t1, t2; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index a035426db57..28bb4d4dec5 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5395,3 +5395,5 @@ ER_TOO_BIG_DISPLAYWIDTH 42000 S1009 eng "Display width out of range for column '%-.64s' (max = %d)" ER_XAER_DUPID XAE08 eng "XAER_DUPID: The XID already exists" +ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG + eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger." diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4c1b8347466..a1f76536f1f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1046,35 +1046,61 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, { // Using table locks TABLE *best_table= 0; int best_distance= INT_MIN; + bool check_if_used= thd->prelocked_mode && + ((int) table_list->lock_type >= + (int) TL_WRITE_ALLOW_WRITE); for (table=thd->open_tables; table ; table=table->next) { if (table->s->key_length == key_length && - !memcmp(table->s->table_cache_key, key, key_length) && - !my_strcasecmp(system_charset_info, table->alias, alias) && - table->query_id != thd->query_id && /* skip tables already used */ - !(thd->prelocked_mode && table->query_id)) + !memcmp(table->s->table_cache_key, key, key_length)) { - int distance= ((int) table->reginfo.lock_type - - (int) table_list->lock_type); - /* - Find a table that either has the exact lock type requested, - or has the best suitable lock. In case there is no locked - table that has an equal or higher lock than requested, - we us the closest matching lock to be able to produce an error - message about wrong lock mode on the table. The best_table is changed - if bd < 0 <= d or bd < d < 0 or 0 <= d < bd. - - distance < 0 - No suitable lock found - distance > 0 - we have lock mode higher then we require - distance == 0 - we have lock mode exactly which we need - */ - if (best_distance < 0 && distance > best_distance || - distance >= 0 && distance < best_distance) + if (check_if_used && table->query_id && + table->query_id != thd->query_id) { - best_distance= distance; - best_table= table; - if (best_distance == 0) // Found perfect lock - break; + /* + If we are in stored function or trigger we should ensure that + we won't change table that is already used by calling statement. + So if we are opening table for writing, we should check that it + is not already open by some calling stamement. + */ + my_error(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG, MYF(0), + table->s->table_name); + DBUG_RETURN(0); + } + if (!my_strcasecmp(system_charset_info, table->alias, alias) && + table->query_id != thd->query_id && /* skip tables already used */ + !(thd->prelocked_mode && table->query_id)) + { + int distance= ((int) table->reginfo.lock_type - + (int) table_list->lock_type); + /* + Find a table that either has the exact lock type requested, + or has the best suitable lock. In case there is no locked + table that has an equal or higher lock than requested, + we us the closest matching lock to be able to produce an error + message about wrong lock mode on the table. The best_table + is changed if bd < 0 <= d or bd < d < 0 or 0 <= d < bd. + + distance < 0 - No suitable lock found + distance > 0 - we have lock mode higher then we require + distance == 0 - we have lock mode exactly which we need + */ + if (best_distance < 0 && distance > best_distance || + distance >= 0 && distance < best_distance) + { + best_distance= distance; + best_table= table; + if (best_distance == 0 && !check_if_used) + { + /* + If we have found perfect match and we don't need to check that + table is not used by one of calling statements (assuming that + we are inside of function or trigger) we can finish iterating + through open tables list. + */ + break; + } + } } } } From 4536a103d06eaead11e948cf211a440bf59eaa33 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 17:29:24 +0200 Subject: [PATCH 16/80] mysqld.dsp: Added archive and example storage engine to Windows build ha_example.cc, ha_archive.cc: Windows fix, use relative include path to "mysql_priv.h" ha_archive.h: Windows VC6 compile needed (char*) cast of byte var mysqltest.dsp, mysql_test_run_new.dsp: Added /FD flag, to avoid include file warnings VC++Files/mysql-test/mysql_test_run_new.dsp: Added /FD flag, to avoid include file warnings VC++Files/client/mysqltest.dsp: Added /FD flag, to avoid include file warnings sql/examples/ha_archive.h: Windows VC6 compile needed (char*) cast of byte var sql/examples/ha_archive.cc: Windows fix, use relative include path to "mysql_priv.h" sql/examples/ha_example.cc: Windows fix, use relative include path to "mysql_priv.h" VC++Files/sql/mysqld.dsp: Added archive and example storage engine to Windows build --- VC++Files/client/mysqltest.dsp | 12 +++++------ VC++Files/mysql-test/mysql_test_run_new.dsp | 8 ++++---- VC++Files/sql/mysqld.dsp | 22 ++++++++++++++------- sql/examples/ha_archive.cc | 2 +- sql/examples/ha_archive.h | 2 +- sql/examples/ha_example.cc | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/VC++Files/client/mysqltest.dsp b/VC++Files/client/mysqltest.dsp index e705b17b0f0..1c636c4d078 100644 --- a/VC++Files/client/mysqltest.dsp +++ b/VC++Files/client/mysqltest.dsp @@ -42,8 +42,8 @@ RSC=rc.exe # PROP Output_Dir ".\debug" # PROP Intermediate_Dir ".\debug" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX -# ADD CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX +# ADD BASE CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX +# ADD CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX # ADD BASE MTL /nologo /tlb".\debug\mysqltest.tlb" /win32 # ADD MTL /nologo /tlb".\debug\mysqltest.tlb" /win32 # ADD BASE RSC /l 1033 /d "_DEBUG" @@ -67,8 +67,8 @@ LINK32=link.exe # PROP Output_Dir ".\classic" # PROP Intermediate_Dir ".\classic" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /c /GX -# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /c /GX +# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX +# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX # ADD BASE MTL /nologo /tlb".\classic\mysqltest.tlb" /win32 # ADD MTL /nologo /tlb".\classic\mysqltest.tlb" /win32 # ADD BASE RSC /l 1033 /d "NDEBUG" @@ -92,8 +92,8 @@ LINK32=link.exe # PROP Output_Dir ".\release" # PROP Intermediate_Dir ".\release" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /c /GX -# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /c /GX +# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX +# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX # ADD BASE MTL /nologo /tlb".\release\mysqltest.tlb" /win32 # ADD MTL /nologo /tlb".\release\mysqltest.tlb" /win32 # ADD BASE RSC /l 1033 /d "NDEBUG" diff --git a/VC++Files/mysql-test/mysql_test_run_new.dsp b/VC++Files/mysql-test/mysql_test_run_new.dsp index 467ff939502..5ff07f0994d 100644 --- a/VC++Files/mysql-test/mysql_test_run_new.dsp +++ b/VC++Files/mysql-test/mysql_test_run_new.dsp @@ -41,8 +41,8 @@ RSC=rc.exe # PROP Output_Dir ".\Debug" # PROP Intermediate_Dir ".\Debug" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_test_run_new.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /c /GX -# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_test_run_new.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /c /GX +# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_test_run_new.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /FD /c /GX +# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_test_run_new.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /FD /c /GX # ADD BASE MTL /nologo /tlb".\Debug\mysql_test_run_new.tlb" /win32 # ADD MTL /nologo /tlb".\Debug\mysql_test_run_new.tlb" /win32 # ADD BASE RSC /l 1033 @@ -66,8 +66,8 @@ LINK32=link.exe # PROP Output_Dir ".\Release" # PROP Intermediate_Dir ".\Release" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_test_run_new.pch" /Fo".\Release/" /Fd".\Release/" /c /GX -# ADD CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_test_run_new.pch" /Fo".\Release/" /Fd".\Release/" /c /GX +# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_test_run_new.pch" /Fo".\Release/" /Fd".\Release/" /FD /c /GX +# ADD CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_test_run_new.pch" /Fo".\Release/" /Fd".\Release/" /FD /c /GX # ADD BASE MTL /nologo /tlb".\Release\mysql_test_run_new.tlb" /win32 # ADD MTL /nologo /tlb".\Release\mysql_test_run_new.tlb" /win32 # ADD BASE RSC /l 1033 diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 6a33889da53..4034ac9f5d0 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -49,7 +49,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x410 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -75,7 +75,7 @@ LINK32=xilink6.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /Fr /YX # ADD BASE RSC /l 0x410 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -102,7 +102,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /MT /W3 /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "DBUG_OFF" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x410 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -130,7 +130,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt-max /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt-max /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -159,7 +159,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-max /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-max /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -215,7 +215,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /D MYSQL_SERVER_SUFFIX=-pro /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /D MYSQL_SERVER_SUFFIX=-pro /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -272,7 +272,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -451,6 +451,14 @@ SOURCE=.\gstream.cpp # End Source File # Begin Source File +SOURCE=.\examples\ha_archive.cpp +# End Source File +# Begin Source File + +SOURCE=.\examples\ha_example.cpp +# End Source File +# Begin Source File + SOURCE=.\ha_blackhole.cpp # End Source File # Begin Source File diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 10712c2e3be..b125f435cfa 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -18,7 +18,7 @@ #pragma implementation // gcc: Class implementation #endif -#include +#include "../mysql_priv.h" #ifdef HAVE_ARCHIVE_DB #include "ha_archive.h" diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 7ab463b6661..52300fda8a2 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -58,7 +58,7 @@ public: ha_archive(TABLE *table): handler(table) { /* Set our original buffer from pre-allocated memory */ - buffer.set(byte_buffer, IO_SIZE, system_charset_info); + buffer.set((char*)byte_buffer, IO_SIZE, system_charset_info); /* The size of the offset value we will use for position() */ ref_length = sizeof(z_off_t); diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc index 31e4e97c5c7..b3edce5ba4a 100644 --- a/sql/examples/ha_example.cc +++ b/sql/examples/ha_example.cc @@ -67,7 +67,7 @@ #pragma implementation // gcc: Class implementation #endif -#include +#include "../mysql_priv.h" #ifdef HAVE_EXAMPLE_DB #include "ha_example.h" From 13c347e7e76f15fb0dc6770355cf44d3af4f3c54 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 22:27:12 +0200 Subject: [PATCH 17/80] ps_conv.inc: Adjustment of float results for Windows mysql-test-run.pl: Added --port to make MYSQL_DUMP and MYSQL_SHOW work on windows have_lowercase0.inc: new file mysql-test/mysql-test-run.pl: Added --port to make MYSQL_DUMP and MYSQL_SHOW work on windows mysql-test/include/ps_conv.inc: Adjustment of float results for Windows --- mysql-test/include/have_lowercase0.inc | 4 ++++ mysql-test/include/ps_conv.inc | 16 ++++++++++++++++ mysql-test/mysql-test-run.pl | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 mysql-test/include/have_lowercase0.inc diff --git a/mysql-test/include/have_lowercase0.inc b/mysql-test/include/have_lowercase0.inc new file mode 100644 index 00000000000..f967c18928b --- /dev/null +++ b/mysql-test/include/have_lowercase0.inc @@ -0,0 +1,4 @@ +--require r/lowercase0.require +--disable_query_log; +show variables like "lower_case_%"; +--enable_query_log; diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc index 0a5bec26fe7..348526202ec 100644 --- a/mysql-test/include/ps_conv.inc +++ b/mysql-test/include/ps_conv.inc @@ -576,15 +576,19 @@ set @arg00= 9223372036854775807 ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; set @arg00= '9223372036854775807' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; # Use the minimum BIGINT from the manual # @@ -592,15 +596,19 @@ set @arg00= -9223372036854775808 ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; set @arg00= '-9223372036854775808' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; # Numeric overflow of columns(c1, c2, c3, c4, c5, c12) with type not in @@ -610,8 +618,10 @@ set @arg00= 1.11111111111111111111e+50 ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; # Attention: The columns(c1,c2,c3,c4,c5,c6) do not get the overflow, # because the string is treated as written integer and @@ -620,15 +630,19 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; set @arg00= -1.11111111111111111111e+50 ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; # Attention: The columns(c1,c2,c3,c4,c5,c6) do not get the overflow, # because the string is treated as written integer and @@ -637,8 +651,10 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; --vertical_results +--replace_result e+0 e+ execute my_select ; --horizontal_results +--replace_result e+0 e+ execute my_delete ; ########################## test of string types ########################## diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 456f481ce86..e72d8f5f683 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2043,6 +2043,7 @@ sub run_mysqltest ($) { my $tinfo= shift; my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " . + "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'} --password="; if ( $opt_debug ) { @@ -2051,6 +2052,7 @@ sub run_mysqltest ($) { } my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " . + "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'} --password="; if ( $opt_debug ) { From 4652c6b0539032fe2f3654f8ec95153ac6eb9305 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Aug 2005 21:40:14 -0600 Subject: [PATCH 18/80] updated patch for BUG#4680 (incomplete DROP DATABASE breaking replication). We binlog the DROP TABLE for each table that was actually dropped. Per Sergei's suggestion a fixed buffer for the DROP TABLE query is pre-allocated from THD pool, and logging now is done in batches - new batch is started if the buffer becomes full. Reduced memory usage by reusing the table list instead of accumulating a list of dropped table names. Also fixed the problem if the table was not actually dropped, eg due to permissions. Extended the test case to make sure batched query logging does work. mysql-test/r/rpl_drop_db.result: test for query buffer overrun mysql-test/t/rpl_drop_db.test: test for query buffer overrun sql/mysql_priv.h: updated patch for BUG#4680 (incomplete DROP DATABASE breaking replication) BitKeeper/etc/ignore: Added support-files/MacOSX/postflight support-files/MacOSX/preflight to the ignore list sql/sql_db.cc: updated patch for BUG#4680 (incomplete DROP DATABASE breaking replication) sql/sql_table.cc: updated patch for BUG#4680 (incomplete DROP DATABASE breaking replication) sql/table.h: updated patch for BUG#4680 (incomplete DROP DATABASE breaking replication) --- .bzrignore | 2 + mysql-test/r/rpl_drop_db.result | 1005 +++++++++++++++++++++++++++++++ mysql-test/t/rpl_drop_db.test | 13 + sql/mysql_priv.h | 2 +- sql/sql_db.cc | 85 ++- sql/sql_table.cc | 23 +- sql/table.h | 3 + 7 files changed, 1085 insertions(+), 48 deletions(-) diff --git a/.bzrignore b/.bzrignore index 7a10ce9db69..f9f9c146692 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1054,3 +1054,5 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl ndb/tools/ndb_config +support-files/MacOSX/postflight +support-files/MacOSX/preflight diff --git a/mysql-test/r/rpl_drop_db.result b/mysql-test/r/rpl_drop_db.result index bafbfe3a1ed..01a2af5341b 100644 --- a/mysql-test/r/rpl_drop_db.result +++ b/mysql-test/r/rpl_drop_db.result @@ -16,6 +16,1011 @@ ERROR HY000: Error dropping database (can't rmdir './d1/', errno: 17) use d1; show tables; Tables_in_d1 +create table d1.t1000(n int); +create table d1.t999(n int); +create table d1.t998(n int); +create table d1.t997(n int); +create table d1.t996(n int); +create table d1.t995(n int); +create table d1.t994(n int); +create table d1.t993(n int); +create table d1.t992(n int); +create table d1.t991(n int); +create table d1.t990(n int); +create table d1.t989(n int); +create table d1.t988(n int); +create table d1.t987(n int); +create table d1.t986(n int); +create table d1.t985(n int); +create table d1.t984(n int); +create table d1.t983(n int); +create table d1.t982(n int); +create table d1.t981(n int); +create table d1.t980(n int); +create table d1.t979(n int); +create table d1.t978(n int); +create table d1.t977(n int); +create table d1.t976(n int); +create table d1.t975(n int); +create table d1.t974(n int); +create table d1.t973(n int); +create table d1.t972(n int); +create table d1.t971(n int); +create table d1.t970(n int); +create table d1.t969(n int); +create table d1.t968(n int); +create table d1.t967(n int); +create table d1.t966(n int); +create table d1.t965(n int); +create table d1.t964(n int); +create table d1.t963(n int); +create table d1.t962(n int); +create table d1.t961(n int); +create table d1.t960(n int); +create table d1.t959(n int); +create table d1.t958(n int); +create table d1.t957(n int); +create table d1.t956(n int); +create table d1.t955(n int); +create table d1.t954(n int); +create table d1.t953(n int); +create table d1.t952(n int); +create table d1.t951(n int); +create table d1.t950(n int); +create table d1.t949(n int); +create table d1.t948(n int); +create table d1.t947(n int); +create table d1.t946(n int); +create table d1.t945(n int); +create table d1.t944(n int); +create table d1.t943(n int); +create table d1.t942(n int); +create table d1.t941(n int); +create table d1.t940(n int); +create table d1.t939(n int); +create table d1.t938(n int); +create table d1.t937(n int); +create table d1.t936(n int); +create table d1.t935(n int); +create table d1.t934(n int); +create table d1.t933(n int); +create table d1.t932(n int); +create table d1.t931(n int); +create table d1.t930(n int); +create table d1.t929(n int); +create table d1.t928(n int); +create table d1.t927(n int); +create table d1.t926(n int); +create table d1.t925(n int); +create table d1.t924(n int); +create table d1.t923(n int); +create table d1.t922(n int); +create table d1.t921(n int); +create table d1.t920(n int); +create table d1.t919(n int); +create table d1.t918(n int); +create table d1.t917(n int); +create table d1.t916(n int); +create table d1.t915(n int); +create table d1.t914(n int); +create table d1.t913(n int); +create table d1.t912(n int); +create table d1.t911(n int); +create table d1.t910(n int); +create table d1.t909(n int); +create table d1.t908(n int); +create table d1.t907(n int); +create table d1.t906(n int); +create table d1.t905(n int); +create table d1.t904(n int); +create table d1.t903(n int); +create table d1.t902(n int); +create table d1.t901(n int); +create table d1.t900(n int); +create table d1.t899(n int); +create table d1.t898(n int); +create table d1.t897(n int); +create table d1.t896(n int); +create table d1.t895(n int); +create table d1.t894(n int); +create table d1.t893(n int); +create table d1.t892(n int); +create table d1.t891(n int); +create table d1.t890(n int); +create table d1.t889(n int); +create table d1.t888(n int); +create table d1.t887(n int); +create table d1.t886(n int); +create table d1.t885(n int); +create table d1.t884(n int); +create table d1.t883(n int); +create table d1.t882(n int); +create table d1.t881(n int); +create table d1.t880(n int); +create table d1.t879(n int); +create table d1.t878(n int); +create table d1.t877(n int); +create table d1.t876(n int); +create table d1.t875(n int); +create table d1.t874(n int); +create table d1.t873(n int); +create table d1.t872(n int); +create table d1.t871(n int); +create table d1.t870(n int); +create table d1.t869(n int); +create table d1.t868(n int); +create table d1.t867(n int); +create table d1.t866(n int); +create table d1.t865(n int); +create table d1.t864(n int); +create table d1.t863(n int); +create table d1.t862(n int); +create table d1.t861(n int); +create table d1.t860(n int); +create table d1.t859(n int); +create table d1.t858(n int); +create table d1.t857(n int); +create table d1.t856(n int); +create table d1.t855(n int); +create table d1.t854(n int); +create table d1.t853(n int); +create table d1.t852(n int); +create table d1.t851(n int); +create table d1.t850(n int); +create table d1.t849(n int); +create table d1.t848(n int); +create table d1.t847(n int); +create table d1.t846(n int); +create table d1.t845(n int); +create table d1.t844(n int); +create table d1.t843(n int); +create table d1.t842(n int); +create table d1.t841(n int); +create table d1.t840(n int); +create table d1.t839(n int); +create table d1.t838(n int); +create table d1.t837(n int); +create table d1.t836(n int); +create table d1.t835(n int); +create table d1.t834(n int); +create table d1.t833(n int); +create table d1.t832(n int); +create table d1.t831(n int); +create table d1.t830(n int); +create table d1.t829(n int); +create table d1.t828(n int); +create table d1.t827(n int); +create table d1.t826(n int); +create table d1.t825(n int); +create table d1.t824(n int); +create table d1.t823(n int); +create table d1.t822(n int); +create table d1.t821(n int); +create table d1.t820(n int); +create table d1.t819(n int); +create table d1.t818(n int); +create table d1.t817(n int); +create table d1.t816(n int); +create table d1.t815(n int); +create table d1.t814(n int); +create table d1.t813(n int); +create table d1.t812(n int); +create table d1.t811(n int); +create table d1.t810(n int); +create table d1.t809(n int); +create table d1.t808(n int); +create table d1.t807(n int); +create table d1.t806(n int); +create table d1.t805(n int); +create table d1.t804(n int); +create table d1.t803(n int); +create table d1.t802(n int); +create table d1.t801(n int); +create table d1.t800(n int); +create table d1.t799(n int); +create table d1.t798(n int); +create table d1.t797(n int); +create table d1.t796(n int); +create table d1.t795(n int); +create table d1.t794(n int); +create table d1.t793(n int); +create table d1.t792(n int); +create table d1.t791(n int); +create table d1.t790(n int); +create table d1.t789(n int); +create table d1.t788(n int); +create table d1.t787(n int); +create table d1.t786(n int); +create table d1.t785(n int); +create table d1.t784(n int); +create table d1.t783(n int); +create table d1.t782(n int); +create table d1.t781(n int); +create table d1.t780(n int); +create table d1.t779(n int); +create table d1.t778(n int); +create table d1.t777(n int); +create table d1.t776(n int); +create table d1.t775(n int); +create table d1.t774(n int); +create table d1.t773(n int); +create table d1.t772(n int); +create table d1.t771(n int); +create table d1.t770(n int); +create table d1.t769(n int); +create table d1.t768(n int); +create table d1.t767(n int); +create table d1.t766(n int); +create table d1.t765(n int); +create table d1.t764(n int); +create table d1.t763(n int); +create table d1.t762(n int); +create table d1.t761(n int); +create table d1.t760(n int); +create table d1.t759(n int); +create table d1.t758(n int); +create table d1.t757(n int); +create table d1.t756(n int); +create table d1.t755(n int); +create table d1.t754(n int); +create table d1.t753(n int); +create table d1.t752(n int); +create table d1.t751(n int); +create table d1.t750(n int); +create table d1.t749(n int); +create table d1.t748(n int); +create table d1.t747(n int); +create table d1.t746(n int); +create table d1.t745(n int); +create table d1.t744(n int); +create table d1.t743(n int); +create table d1.t742(n int); +create table d1.t741(n int); +create table d1.t740(n int); +create table d1.t739(n int); +create table d1.t738(n int); +create table d1.t737(n int); +create table d1.t736(n int); +create table d1.t735(n int); +create table d1.t734(n int); +create table d1.t733(n int); +create table d1.t732(n int); +create table d1.t731(n int); +create table d1.t730(n int); +create table d1.t729(n int); +create table d1.t728(n int); +create table d1.t727(n int); +create table d1.t726(n int); +create table d1.t725(n int); +create table d1.t724(n int); +create table d1.t723(n int); +create table d1.t722(n int); +create table d1.t721(n int); +create table d1.t720(n int); +create table d1.t719(n int); +create table d1.t718(n int); +create table d1.t717(n int); +create table d1.t716(n int); +create table d1.t715(n int); +create table d1.t714(n int); +create table d1.t713(n int); +create table d1.t712(n int); +create table d1.t711(n int); +create table d1.t710(n int); +create table d1.t709(n int); +create table d1.t708(n int); +create table d1.t707(n int); +create table d1.t706(n int); +create table d1.t705(n int); +create table d1.t704(n int); +create table d1.t703(n int); +create table d1.t702(n int); +create table d1.t701(n int); +create table d1.t700(n int); +create table d1.t699(n int); +create table d1.t698(n int); +create table d1.t697(n int); +create table d1.t696(n int); +create table d1.t695(n int); +create table d1.t694(n int); +create table d1.t693(n int); +create table d1.t692(n int); +create table d1.t691(n int); +create table d1.t690(n int); +create table d1.t689(n int); +create table d1.t688(n int); +create table d1.t687(n int); +create table d1.t686(n int); +create table d1.t685(n int); +create table d1.t684(n int); +create table d1.t683(n int); +create table d1.t682(n int); +create table d1.t681(n int); +create table d1.t680(n int); +create table d1.t679(n int); +create table d1.t678(n int); +create table d1.t677(n int); +create table d1.t676(n int); +create table d1.t675(n int); +create table d1.t674(n int); +create table d1.t673(n int); +create table d1.t672(n int); +create table d1.t671(n int); +create table d1.t670(n int); +create table d1.t669(n int); +create table d1.t668(n int); +create table d1.t667(n int); +create table d1.t666(n int); +create table d1.t665(n int); +create table d1.t664(n int); +create table d1.t663(n int); +create table d1.t662(n int); +create table d1.t661(n int); +create table d1.t660(n int); +create table d1.t659(n int); +create table d1.t658(n int); +create table d1.t657(n int); +create table d1.t656(n int); +create table d1.t655(n int); +create table d1.t654(n int); +create table d1.t653(n int); +create table d1.t652(n int); +create table d1.t651(n int); +create table d1.t650(n int); +create table d1.t649(n int); +create table d1.t648(n int); +create table d1.t647(n int); +create table d1.t646(n int); +create table d1.t645(n int); +create table d1.t644(n int); +create table d1.t643(n int); +create table d1.t642(n int); +create table d1.t641(n int); +create table d1.t640(n int); +create table d1.t639(n int); +create table d1.t638(n int); +create table d1.t637(n int); +create table d1.t636(n int); +create table d1.t635(n int); +create table d1.t634(n int); +create table d1.t633(n int); +create table d1.t632(n int); +create table d1.t631(n int); +create table d1.t630(n int); +create table d1.t629(n int); +create table d1.t628(n int); +create table d1.t627(n int); +create table d1.t626(n int); +create table d1.t625(n int); +create table d1.t624(n int); +create table d1.t623(n int); +create table d1.t622(n int); +create table d1.t621(n int); +create table d1.t620(n int); +create table d1.t619(n int); +create table d1.t618(n int); +create table d1.t617(n int); +create table d1.t616(n int); +create table d1.t615(n int); +create table d1.t614(n int); +create table d1.t613(n int); +create table d1.t612(n int); +create table d1.t611(n int); +create table d1.t610(n int); +create table d1.t609(n int); +create table d1.t608(n int); +create table d1.t607(n int); +create table d1.t606(n int); +create table d1.t605(n int); +create table d1.t604(n int); +create table d1.t603(n int); +create table d1.t602(n int); +create table d1.t601(n int); +create table d1.t600(n int); +create table d1.t599(n int); +create table d1.t598(n int); +create table d1.t597(n int); +create table d1.t596(n int); +create table d1.t595(n int); +create table d1.t594(n int); +create table d1.t593(n int); +create table d1.t592(n int); +create table d1.t591(n int); +create table d1.t590(n int); +create table d1.t589(n int); +create table d1.t588(n int); +create table d1.t587(n int); +create table d1.t586(n int); +create table d1.t585(n int); +create table d1.t584(n int); +create table d1.t583(n int); +create table d1.t582(n int); +create table d1.t581(n int); +create table d1.t580(n int); +create table d1.t579(n int); +create table d1.t578(n int); +create table d1.t577(n int); +create table d1.t576(n int); +create table d1.t575(n int); +create table d1.t574(n int); +create table d1.t573(n int); +create table d1.t572(n int); +create table d1.t571(n int); +create table d1.t570(n int); +create table d1.t569(n int); +create table d1.t568(n int); +create table d1.t567(n int); +create table d1.t566(n int); +create table d1.t565(n int); +create table d1.t564(n int); +create table d1.t563(n int); +create table d1.t562(n int); +create table d1.t561(n int); +create table d1.t560(n int); +create table d1.t559(n int); +create table d1.t558(n int); +create table d1.t557(n int); +create table d1.t556(n int); +create table d1.t555(n int); +create table d1.t554(n int); +create table d1.t553(n int); +create table d1.t552(n int); +create table d1.t551(n int); +create table d1.t550(n int); +create table d1.t549(n int); +create table d1.t548(n int); +create table d1.t547(n int); +create table d1.t546(n int); +create table d1.t545(n int); +create table d1.t544(n int); +create table d1.t543(n int); +create table d1.t542(n int); +create table d1.t541(n int); +create table d1.t540(n int); +create table d1.t539(n int); +create table d1.t538(n int); +create table d1.t537(n int); +create table d1.t536(n int); +create table d1.t535(n int); +create table d1.t534(n int); +create table d1.t533(n int); +create table d1.t532(n int); +create table d1.t531(n int); +create table d1.t530(n int); +create table d1.t529(n int); +create table d1.t528(n int); +create table d1.t527(n int); +create table d1.t526(n int); +create table d1.t525(n int); +create table d1.t524(n int); +create table d1.t523(n int); +create table d1.t522(n int); +create table d1.t521(n int); +create table d1.t520(n int); +create table d1.t519(n int); +create table d1.t518(n int); +create table d1.t517(n int); +create table d1.t516(n int); +create table d1.t515(n int); +create table d1.t514(n int); +create table d1.t513(n int); +create table d1.t512(n int); +create table d1.t511(n int); +create table d1.t510(n int); +create table d1.t509(n int); +create table d1.t508(n int); +create table d1.t507(n int); +create table d1.t506(n int); +create table d1.t505(n int); +create table d1.t504(n int); +create table d1.t503(n int); +create table d1.t502(n int); +create table d1.t501(n int); +create table d1.t500(n int); +create table d1.t499(n int); +create table d1.t498(n int); +create table d1.t497(n int); +create table d1.t496(n int); +create table d1.t495(n int); +create table d1.t494(n int); +create table d1.t493(n int); +create table d1.t492(n int); +create table d1.t491(n int); +create table d1.t490(n int); +create table d1.t489(n int); +create table d1.t488(n int); +create table d1.t487(n int); +create table d1.t486(n int); +create table d1.t485(n int); +create table d1.t484(n int); +create table d1.t483(n int); +create table d1.t482(n int); +create table d1.t481(n int); +create table d1.t480(n int); +create table d1.t479(n int); +create table d1.t478(n int); +create table d1.t477(n int); +create table d1.t476(n int); +create table d1.t475(n int); +create table d1.t474(n int); +create table d1.t473(n int); +create table d1.t472(n int); +create table d1.t471(n int); +create table d1.t470(n int); +create table d1.t469(n int); +create table d1.t468(n int); +create table d1.t467(n int); +create table d1.t466(n int); +create table d1.t465(n int); +create table d1.t464(n int); +create table d1.t463(n int); +create table d1.t462(n int); +create table d1.t461(n int); +create table d1.t460(n int); +create table d1.t459(n int); +create table d1.t458(n int); +create table d1.t457(n int); +create table d1.t456(n int); +create table d1.t455(n int); +create table d1.t454(n int); +create table d1.t453(n int); +create table d1.t452(n int); +create table d1.t451(n int); +create table d1.t450(n int); +create table d1.t449(n int); +create table d1.t448(n int); +create table d1.t447(n int); +create table d1.t446(n int); +create table d1.t445(n int); +create table d1.t444(n int); +create table d1.t443(n int); +create table d1.t442(n int); +create table d1.t441(n int); +create table d1.t440(n int); +create table d1.t439(n int); +create table d1.t438(n int); +create table d1.t437(n int); +create table d1.t436(n int); +create table d1.t435(n int); +create table d1.t434(n int); +create table d1.t433(n int); +create table d1.t432(n int); +create table d1.t431(n int); +create table d1.t430(n int); +create table d1.t429(n int); +create table d1.t428(n int); +create table d1.t427(n int); +create table d1.t426(n int); +create table d1.t425(n int); +create table d1.t424(n int); +create table d1.t423(n int); +create table d1.t422(n int); +create table d1.t421(n int); +create table d1.t420(n int); +create table d1.t419(n int); +create table d1.t418(n int); +create table d1.t417(n int); +create table d1.t416(n int); +create table d1.t415(n int); +create table d1.t414(n int); +create table d1.t413(n int); +create table d1.t412(n int); +create table d1.t411(n int); +create table d1.t410(n int); +create table d1.t409(n int); +create table d1.t408(n int); +create table d1.t407(n int); +create table d1.t406(n int); +create table d1.t405(n int); +create table d1.t404(n int); +create table d1.t403(n int); +create table d1.t402(n int); +create table d1.t401(n int); +create table d1.t400(n int); +create table d1.t399(n int); +create table d1.t398(n int); +create table d1.t397(n int); +create table d1.t396(n int); +create table d1.t395(n int); +create table d1.t394(n int); +create table d1.t393(n int); +create table d1.t392(n int); +create table d1.t391(n int); +create table d1.t390(n int); +create table d1.t389(n int); +create table d1.t388(n int); +create table d1.t387(n int); +create table d1.t386(n int); +create table d1.t385(n int); +create table d1.t384(n int); +create table d1.t383(n int); +create table d1.t382(n int); +create table d1.t381(n int); +create table d1.t380(n int); +create table d1.t379(n int); +create table d1.t378(n int); +create table d1.t377(n int); +create table d1.t376(n int); +create table d1.t375(n int); +create table d1.t374(n int); +create table d1.t373(n int); +create table d1.t372(n int); +create table d1.t371(n int); +create table d1.t370(n int); +create table d1.t369(n int); +create table d1.t368(n int); +create table d1.t367(n int); +create table d1.t366(n int); +create table d1.t365(n int); +create table d1.t364(n int); +create table d1.t363(n int); +create table d1.t362(n int); +create table d1.t361(n int); +create table d1.t360(n int); +create table d1.t359(n int); +create table d1.t358(n int); +create table d1.t357(n int); +create table d1.t356(n int); +create table d1.t355(n int); +create table d1.t354(n int); +create table d1.t353(n int); +create table d1.t352(n int); +create table d1.t351(n int); +create table d1.t350(n int); +create table d1.t349(n int); +create table d1.t348(n int); +create table d1.t347(n int); +create table d1.t346(n int); +create table d1.t345(n int); +create table d1.t344(n int); +create table d1.t343(n int); +create table d1.t342(n int); +create table d1.t341(n int); +create table d1.t340(n int); +create table d1.t339(n int); +create table d1.t338(n int); +create table d1.t337(n int); +create table d1.t336(n int); +create table d1.t335(n int); +create table d1.t334(n int); +create table d1.t333(n int); +create table d1.t332(n int); +create table d1.t331(n int); +create table d1.t330(n int); +create table d1.t329(n int); +create table d1.t328(n int); +create table d1.t327(n int); +create table d1.t326(n int); +create table d1.t325(n int); +create table d1.t324(n int); +create table d1.t323(n int); +create table d1.t322(n int); +create table d1.t321(n int); +create table d1.t320(n int); +create table d1.t319(n int); +create table d1.t318(n int); +create table d1.t317(n int); +create table d1.t316(n int); +create table d1.t315(n int); +create table d1.t314(n int); +create table d1.t313(n int); +create table d1.t312(n int); +create table d1.t311(n int); +create table d1.t310(n int); +create table d1.t309(n int); +create table d1.t308(n int); +create table d1.t307(n int); +create table d1.t306(n int); +create table d1.t305(n int); +create table d1.t304(n int); +create table d1.t303(n int); +create table d1.t302(n int); +create table d1.t301(n int); +create table d1.t300(n int); +create table d1.t299(n int); +create table d1.t298(n int); +create table d1.t297(n int); +create table d1.t296(n int); +create table d1.t295(n int); +create table d1.t294(n int); +create table d1.t293(n int); +create table d1.t292(n int); +create table d1.t291(n int); +create table d1.t290(n int); +create table d1.t289(n int); +create table d1.t288(n int); +create table d1.t287(n int); +create table d1.t286(n int); +create table d1.t285(n int); +create table d1.t284(n int); +create table d1.t283(n int); +create table d1.t282(n int); +create table d1.t281(n int); +create table d1.t280(n int); +create table d1.t279(n int); +create table d1.t278(n int); +create table d1.t277(n int); +create table d1.t276(n int); +create table d1.t275(n int); +create table d1.t274(n int); +create table d1.t273(n int); +create table d1.t272(n int); +create table d1.t271(n int); +create table d1.t270(n int); +create table d1.t269(n int); +create table d1.t268(n int); +create table d1.t267(n int); +create table d1.t266(n int); +create table d1.t265(n int); +create table d1.t264(n int); +create table d1.t263(n int); +create table d1.t262(n int); +create table d1.t261(n int); +create table d1.t260(n int); +create table d1.t259(n int); +create table d1.t258(n int); +create table d1.t257(n int); +create table d1.t256(n int); +create table d1.t255(n int); +create table d1.t254(n int); +create table d1.t253(n int); +create table d1.t252(n int); +create table d1.t251(n int); +create table d1.t250(n int); +create table d1.t249(n int); +create table d1.t248(n int); +create table d1.t247(n int); +create table d1.t246(n int); +create table d1.t245(n int); +create table d1.t244(n int); +create table d1.t243(n int); +create table d1.t242(n int); +create table d1.t241(n int); +create table d1.t240(n int); +create table d1.t239(n int); +create table d1.t238(n int); +create table d1.t237(n int); +create table d1.t236(n int); +create table d1.t235(n int); +create table d1.t234(n int); +create table d1.t233(n int); +create table d1.t232(n int); +create table d1.t231(n int); +create table d1.t230(n int); +create table d1.t229(n int); +create table d1.t228(n int); +create table d1.t227(n int); +create table d1.t226(n int); +create table d1.t225(n int); +create table d1.t224(n int); +create table d1.t223(n int); +create table d1.t222(n int); +create table d1.t221(n int); +create table d1.t220(n int); +create table d1.t219(n int); +create table d1.t218(n int); +create table d1.t217(n int); +create table d1.t216(n int); +create table d1.t215(n int); +create table d1.t214(n int); +create table d1.t213(n int); +create table d1.t212(n int); +create table d1.t211(n int); +create table d1.t210(n int); +create table d1.t209(n int); +create table d1.t208(n int); +create table d1.t207(n int); +create table d1.t206(n int); +create table d1.t205(n int); +create table d1.t204(n int); +create table d1.t203(n int); +create table d1.t202(n int); +create table d1.t201(n int); +create table d1.t200(n int); +create table d1.t199(n int); +create table d1.t198(n int); +create table d1.t197(n int); +create table d1.t196(n int); +create table d1.t195(n int); +create table d1.t194(n int); +create table d1.t193(n int); +create table d1.t192(n int); +create table d1.t191(n int); +create table d1.t190(n int); +create table d1.t189(n int); +create table d1.t188(n int); +create table d1.t187(n int); +create table d1.t186(n int); +create table d1.t185(n int); +create table d1.t184(n int); +create table d1.t183(n int); +create table d1.t182(n int); +create table d1.t181(n int); +create table d1.t180(n int); +create table d1.t179(n int); +create table d1.t178(n int); +create table d1.t177(n int); +create table d1.t176(n int); +create table d1.t175(n int); +create table d1.t174(n int); +create table d1.t173(n int); +create table d1.t172(n int); +create table d1.t171(n int); +create table d1.t170(n int); +create table d1.t169(n int); +create table d1.t168(n int); +create table d1.t167(n int); +create table d1.t166(n int); +create table d1.t165(n int); +create table d1.t164(n int); +create table d1.t163(n int); +create table d1.t162(n int); +create table d1.t161(n int); +create table d1.t160(n int); +create table d1.t159(n int); +create table d1.t158(n int); +create table d1.t157(n int); +create table d1.t156(n int); +create table d1.t155(n int); +create table d1.t154(n int); +create table d1.t153(n int); +create table d1.t152(n int); +create table d1.t151(n int); +create table d1.t150(n int); +create table d1.t149(n int); +create table d1.t148(n int); +create table d1.t147(n int); +create table d1.t146(n int); +create table d1.t145(n int); +create table d1.t144(n int); +create table d1.t143(n int); +create table d1.t142(n int); +create table d1.t141(n int); +create table d1.t140(n int); +create table d1.t139(n int); +create table d1.t138(n int); +create table d1.t137(n int); +create table d1.t136(n int); +create table d1.t135(n int); +create table d1.t134(n int); +create table d1.t133(n int); +create table d1.t132(n int); +create table d1.t131(n int); +create table d1.t130(n int); +create table d1.t129(n int); +create table d1.t128(n int); +create table d1.t127(n int); +create table d1.t126(n int); +create table d1.t125(n int); +create table d1.t124(n int); +create table d1.t123(n int); +create table d1.t122(n int); +create table d1.t121(n int); +create table d1.t120(n int); +create table d1.t119(n int); +create table d1.t118(n int); +create table d1.t117(n int); +create table d1.t116(n int); +create table d1.t115(n int); +create table d1.t114(n int); +create table d1.t113(n int); +create table d1.t112(n int); +create table d1.t111(n int); +create table d1.t110(n int); +create table d1.t109(n int); +create table d1.t108(n int); +create table d1.t107(n int); +create table d1.t106(n int); +create table d1.t105(n int); +create table d1.t104(n int); +create table d1.t103(n int); +create table d1.t102(n int); +create table d1.t101(n int); +create table d1.t100(n int); +create table d1.t99(n int); +create table d1.t98(n int); +create table d1.t97(n int); +create table d1.t96(n int); +create table d1.t95(n int); +create table d1.t94(n int); +create table d1.t93(n int); +create table d1.t92(n int); +create table d1.t91(n int); +create table d1.t90(n int); +create table d1.t89(n int); +create table d1.t88(n int); +create table d1.t87(n int); +create table d1.t86(n int); +create table d1.t85(n int); +create table d1.t84(n int); +create table d1.t83(n int); +create table d1.t82(n int); +create table d1.t81(n int); +create table d1.t80(n int); +create table d1.t79(n int); +create table d1.t78(n int); +create table d1.t77(n int); +create table d1.t76(n int); +create table d1.t75(n int); +create table d1.t74(n int); +create table d1.t73(n int); +create table d1.t72(n int); +create table d1.t71(n int); +create table d1.t70(n int); +create table d1.t69(n int); +create table d1.t68(n int); +create table d1.t67(n int); +create table d1.t66(n int); +create table d1.t65(n int); +create table d1.t64(n int); +create table d1.t63(n int); +create table d1.t62(n int); +create table d1.t61(n int); +create table d1.t60(n int); +create table d1.t59(n int); +create table d1.t58(n int); +create table d1.t57(n int); +create table d1.t56(n int); +create table d1.t55(n int); +create table d1.t54(n int); +create table d1.t53(n int); +create table d1.t52(n int); +create table d1.t51(n int); +create table d1.t50(n int); +create table d1.t49(n int); +create table d1.t48(n int); +create table d1.t47(n int); +create table d1.t46(n int); +create table d1.t45(n int); +create table d1.t44(n int); +create table d1.t43(n int); +create table d1.t42(n int); +create table d1.t41(n int); +create table d1.t40(n int); +create table d1.t39(n int); +create table d1.t38(n int); +create table d1.t37(n int); +create table d1.t36(n int); +create table d1.t35(n int); +create table d1.t34(n int); +create table d1.t33(n int); +create table d1.t32(n int); +create table d1.t31(n int); +create table d1.t30(n int); +create table d1.t29(n int); +create table d1.t28(n int); +create table d1.t27(n int); +create table d1.t26(n int); +create table d1.t25(n int); +create table d1.t24(n int); +create table d1.t23(n int); +create table d1.t22(n int); +create table d1.t21(n int); +create table d1.t20(n int); +create table d1.t19(n int); +create table d1.t18(n int); +create table d1.t17(n int); +create table d1.t16(n int); +create table d1.t15(n int); +create table d1.t14(n int); +create table d1.t13(n int); +create table d1.t12(n int); +create table d1.t11(n int); +create table d1.t10(n int); +create table d1.t9(n int); +create table d1.t8(n int); +create table d1.t7(n int); +create table d1.t6(n int); +create table d1.t5(n int); +create table d1.t4(n int); +create table d1.t3(n int); +create table d1.t2(n int); +create table d1.t1(n int); +drop database d1; +ERROR HY000: Error dropping database (can't rmdir './d1/', errno: 17) +use d1; +show tables; +Tables_in_d1 use test; create table t1 (n int); insert into t1 values (1234); diff --git a/mysql-test/t/rpl_drop_db.test b/mysql-test/t/rpl_drop_db.test index ef0ab4be6fd..71dc22f705f 100644 --- a/mysql-test/t/rpl_drop_db.test +++ b/mysql-test/t/rpl_drop_db.test @@ -17,6 +17,19 @@ create table d1.t3 (n int); drop database d1; use d1; show tables; + +# test the branch of the code that deals with the query buffer overflow + +let $1=1000; +while ($1) +{ + eval create table d1.t$1(n int); + dec $1; +} +--error 1010 +drop database d1; +use d1; +show tables; use test; create table t1 (n int); insert into t1 values (1234); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 946bb117e9e..0af3ea3af63 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -447,7 +447,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool log_query); int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, - bool log_query, List *dropped_tables); + bool log_query); int quick_rm_table(enum db_type base,const char *db, const char *table_name); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 0155fca0466..6dcc7be0904 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,14 +25,20 @@ #include #endif +#define MAX_DROP_TABLE_Q_LEN 1024 + const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts, NULL}; static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, - const char *db, const char *path, - uint level, List *dropped_tables); + const char *db, const char *path, uint level, + TABLE_LIST** dropped_tables); + +static inline void write_to_binlog(THD* thd, char* query, uint q_len, + char* db, uint db_len); + /* Database options hash */ static HASH dboptions; static my_bool dboptions_init= 0; @@ -57,6 +63,19 @@ static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, return (byte*) opt->name; } +/* + Helper function to write a query to binlog used by mysql_rm_db() + */ +static inline void write_to_binlog(THD* thd, char* query, uint q_len, + char* db, uint db_len) +{ + Query_log_event qinfo(thd, query, q_len, 0, 0); + qinfo.error_code= 0; + qinfo.db= db; + qinfo.db_len= db_len; + mysql_bin_log.write(&qinfo); +} + /* Function to free dboptions hash element @@ -584,8 +603,8 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) int error= 0; char path[FN_REFLEN+16], tmp_db[NAME_LEN+1]; MY_DIR *dirp; - List dropped_tables; uint length; + TABLE_LIST* dropped_tables= 0; DBUG_ENTER("mysql_rm_db"); VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -625,7 +644,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) error= -1; if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0, - &dropped_tables)) >= 0) + &dropped_tables)) >= 0) { ha_drop_database(path); query_cache_invalidate1(db); @@ -675,36 +694,44 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) send_ok(thd, (ulong) deleted); thd->server_status&= ~SERVER_STATUS_DB_DROPPED; } - else if (!dropped_tables.is_empty() && mysql_bin_log.is_open()) + else if (mysql_bin_log.is_open()) { - List_iterator it(dropped_tables); - String* dropped_table; - int q_len= 11; /* drop table */ - int db_len= strlen(db); + char* query= thd->alloc(MAX_DROP_TABLE_Q_LEN); - for (;(dropped_table= it++);) - { - q_len += dropped_table->length() + 2 + db_len; - } - q_len--; /* no last comma */ - - char* query= thd->alloc(q_len); if (!query) goto exit; /* not much else we can do */ char* p= strmov(query,"drop table "); - it.rewind(); + char* p_end= query + MAX_DROP_TABLE_Q_LEN; + TABLE_LIST* tbl; + bool last_query_needs_write= 0; + uint db_len= strlen(db); - for (;(dropped_table= it++);) + for (tbl= dropped_tables;tbl;tbl= tbl->next) { - p= strmov(p,db); - *p++ = '.'; - p= strnmov(p,dropped_table->ptr(),dropped_table->length()); + if (!tbl->was_dropped) + continue; + + /* 3 for the quotes and the comma*/ + uint tbl_name_len= strlen(tbl->real_name) + 3; + if (p + tbl_name_len + 1 >= p_end) + { + *--p= 0; /* kill , */ + write_to_binlog(thd, query, p - query, db, db_len); + p= query + 11; /* reuse the initial "drop table" */ + } + + *p++ = '`'; + p= strmov(p,tbl->real_name); + *p++ = '`'; *p++ = ','; + last_query_needs_write= 1; } - *--p= 0; - Query_log_event qinfo(thd, query, q_len, 0, 0); - qinfo.error_code= 0; - mysql_bin_log.write(&qinfo); + + if (last_query_needs_write) + { + *--p= 0; + write_to_binlog(thd, query, p - query, db, db_len); + } } exit: @@ -750,7 +777,7 @@ exit2: */ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, - const char *org_path, uint level, List *dropped_tables) + const char *org_path, uint level, TABLE_LIST** dropped_tables) { long deleted=0; ulong found_other_files=0; @@ -839,8 +866,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, } } if (thd->killed || - (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, - 1,dropped_tables))) + (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1))) goto err; /* Remove RAID directories */ @@ -853,6 +879,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, } my_dirend(dirp); + if (dropped_tables) + *dropped_tables= tot_list; + /* If the directory is a symbolic link, remove the link first, then remove the directory the symbolic link pointed at diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e948a65f301..80ac9e007b9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -156,8 +156,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, bool if_exists, - bool drop_temporary, bool dont_log_query, - List* dropped_tables) + bool drop_temporary, bool dont_log_query) { int error; thd->mysys_var->current_mutex= &LOCK_open; @@ -166,23 +165,6 @@ int mysql_rm_table_part2_with_lock(THD *thd, error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, dont_log_query); - /* - For now we assume that if we got success all the tables in the list - were actually dropped, otherwise, assume none were dropped. - TODO: fix it to work with a partial drop - extremely rare case, but - can happen. - */ - if (!error && dropped_tables) - { - TABLE_LIST* tbl; - - for (tbl= tables; tbl; tbl= tbl->next) - { - String *dropped_table= new (thd->mem_root) - String(tbl->real_name,&my_charset_latin1); - dropped_tables->push_back(dropped_table); - } - } pthread_mutex_unlock(&LOCK_open); @@ -238,6 +220,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, for (table=tables ; table ; table=table->next) { char *db=table->db; + table->was_dropped= 0; mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL); if (!close_temporary_table(thd, db, table->real_name)) { @@ -298,6 +281,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(','); wrong_tables.append(String(table->real_name,system_charset_info)); } + else + table->was_dropped= 1; } thd->tmp_table_used= tmp_table_deleted; error= 0; diff --git a/sql/table.h b/sql/table.h index 77153e5d8cd..fb742acf804 100644 --- a/sql/table.h +++ b/sql/table.h @@ -235,6 +235,9 @@ typedef struct st_table_list bool cacheable_table; /* stop PS caching */ /* used in multi-upd privelege check */ bool table_in_update_from_clause; + + /* used for proper partially successful DROP DATABASE binlogging */ + bool was_dropped; } TABLE_LIST; typedef struct st_changed_table_list From af1652d561fc28d607fa84f1c56e9fa8fd3b2644 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 07:48:59 +0200 Subject: [PATCH 19/80] ndb rename config.cpp -> ndb_config.cpp for case insesitive filesystems why wasn't this done in 4.1 directly ndb/tools/ndb_config.cpp: Rename: ndb/tools/config.cpp -> ndb/tools/ndb_config.cpp mysql-test/t/ndb_config.test: remove include only present in 5.0 ndb/tools/Makefile.am: rename config.cpp -> ndb_config.cpp for case insesitive filesystems why wasn't this done in 4.1 directly --- mysql-test/t/ndb_config.test | 1 - ndb/tools/Makefile.am | 2 +- ndb/tools/{config.cpp => ndb_config.cpp} | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename ndb/tools/{config.cpp => ndb_config.cpp} (100%) diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test index a79973515b2..ea78a32b1ba 100644 --- a/mysql-test/t/ndb_config.test +++ b/mysql-test/t/ndb_config.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/ndb_default_cluster.inc -- source include/not_embedded.inc --exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=type,nodeid,host 2> /dev/null diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am index 1f11122fb70..89830129576 100644 --- a/ndb/tools/Makefile.am +++ b/ndb/tools/Makefile.am @@ -32,7 +32,7 @@ ndb_restore_SOURCES = restore/restore_main.cpp \ restore/consumer_printer.cpp \ restore/Restore.cpp -ndb_config_SOURCES = config.cpp \ +ndb_config_SOURCES = ndb_config.cpp \ ../src/mgmsrv/Config.cpp \ ../src/mgmsrv/ConfigInfo.cpp \ ../src/mgmsrv/InitConfigFileParser.cpp diff --git a/ndb/tools/config.cpp b/ndb/tools/ndb_config.cpp similarity index 100% rename from ndb/tools/config.cpp rename to ndb/tools/ndb_config.cpp From 83fbcef16ad68adebdcb4365efbc0e964c32a3a3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 09:04:30 +0200 Subject: [PATCH 20/80] jonas - Fix checkout properties BitKeeper/etc/config: Fix checkout properties --- BitKeeper/etc/config | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 6ddd492ebc4..0f0666d5050 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -70,5 +70,6 @@ hours: [serg:]checkout:get [arjen:]checkout:get [nick:]checkout:get +[jonas:]checkout:get checkout:edit eoln:unix From 9c668f7f02b0c4f4a05fe801b259187230184afd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 10:12:44 +0200 Subject: [PATCH 21/80] ndb - remove grep from Makefile ndb/src/kernel/Makefile.am: remove grep from Makefile --- ndb/src/kernel/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 55d3c5a578f..389cb85c1d8 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -23,7 +23,6 @@ INCLUDES += \ -Iblocks/backup \ -Iblocks/dbutil \ -Iblocks/suma \ - -Iblocks/grep \ -Iblocks/dbtux LDADD += \ @@ -41,7 +40,6 @@ LDADD += \ blocks/backup/libbackup.a \ blocks/dbutil/libdbutil.a \ blocks/suma/libsuma.a \ - blocks/grep/libgrep.a \ blocks/dbtux/libdbtux.a \ vm/libkernel.a \ error/liberror.a \ From d0c821d360a7ec2c1d3e0e996ef136a92932991d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 10:24:37 +0200 Subject: [PATCH 22/80] jonas: fix bk checkout properties --- BitKeeper/etc/config | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 56ae08e5ffa..d9c45d3d36a 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -71,5 +71,6 @@ hours: [arjen:]checkout:get [kostja:]checkout:get [nick:]checkout:get +[jonas:]checkout:get checkout:edit eoln:unix From 01f4258a02e01f578c0552089ef313ddc4bf95c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 01:57:22 -0700 Subject: [PATCH 23/80] distinct.test, distinct.result: Added test cases for bug #12625. sql_select.cc: Fixed bug #12625. Fixed invalid removal of constant items from the DISTINCT list in the function create_distinct_group. sql/sql_select.cc: Fixed bug #12625. mysql-test/r/distinct.result: Added test cases for bug #12625. mysql-test/t/distinct.test: Added test cases for bug #12625. --- mysql-test/r/distinct.result | 40 ++++++++++++++++++++++++++++++++++++ mysql-test/t/distinct.test | 17 +++++++++++++++ sql/sql_select.cc | 4 +--- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index f4bc4263c4d..8932285b5d0 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -464,3 +464,43 @@ SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; html prod 1 0.00 drop table t1; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SELECT DISTINCT a, 1 FROM t1; +a 1 +1 1 +2 1 +3 1 +4 1 +5 1 +SELECT DISTINCT 1, a FROM t1; +1 a +1 1 +1 2 +1 3 +1 4 +1 5 +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES (1,1),(2,2),(2,3),(2,4),(3,5); +SELECT DISTINCT a, b, 2 FROM t2; +a b 2 +1 1 2 +2 2 2 +2 3 2 +2 4 2 +3 5 2 +SELECT DISTINCT 2, a, b FROM t2; +2 a b +2 1 1 +2 2 2 +2 2 3 +2 2 4 +2 3 5 +SELECT DISTINCT a, 2, b FROM t2; +a 2 b +1 2 1 +2 2 2 +2 2 3 +2 2 4 +3 2 5 +DROP TABLE t1,t2; diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index f05dd4b75a0..f2fe1ec6372 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -333,4 +333,21 @@ INSERT INTO t1 VALUES ('1',1,0); SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; drop table t1; +# +# Test cases for #12625: DISTINCT for a list with constants +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SELECT DISTINCT a, 1 FROM t1; +SELECT DISTINCT 1, a FROM t1; + +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES (1,1),(2,2),(2,3),(2,4),(3,5); +SELECT DISTINCT a, b, 2 FROM t2; +SELECT DISTINCT 2, a, b FROM t2; +SELECT DISTINCT a, 2, b FROM t2; + +DROP TABLE t1,t2; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9984cb4138f..3b67af8eea7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8517,9 +8517,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, li.rewind(); while ((item=li++)) { - if (item->const_item() || item->with_sum_func) - continue; - if (!item->marker) + if (!item->const_item() && !item->with_sum_func && !item->marker) { ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) From 81a54a7953f99cd989ee0d3c59d576a884905089 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 13:20:36 +0200 Subject: [PATCH 24/80] ndb remove grep stuff ndb/src/kernel/Makefile.am: remove grep stuff --- ndb/src/kernel/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 55d3c5a578f..389cb85c1d8 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -23,7 +23,6 @@ INCLUDES += \ -Iblocks/backup \ -Iblocks/dbutil \ -Iblocks/suma \ - -Iblocks/grep \ -Iblocks/dbtux LDADD += \ @@ -41,7 +40,6 @@ LDADD += \ blocks/backup/libbackup.a \ blocks/dbutil/libdbutil.a \ blocks/suma/libsuma.a \ - blocks/grep/libgrep.a \ blocks/dbtux/libdbtux.a \ vm/libkernel.a \ error/liberror.a \ From 3e946906272009aac5145f85421992f78ba4eff0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 16:25:55 +0200 Subject: [PATCH 25/80] BUG#12532: Added more memory in malloc for slave query cache sql/log_event.cc: Added memory to malloc sql/sql_cache.cc: Added comment --- sql/log_event.cc | 8 +++++++- sql/sql_cache.cc | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index bdf17ba20e3..5b9287f03ac 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1330,7 +1330,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + time_zone_len + 1 + - data_len + 1, MYF(MY_WME)))) + data_len + 1 + +#ifndef MYSQL_CLIENT +#ifdef HAVE_QUERY_CACHE + QUERY_CACHE_FLAGS_SIZE + +#endif +#endif + db_len + 1, MYF(MY_WME)))) DBUG_VOID_RETURN; if (catalog_len) // If catalog is given { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 0f4fdd52583..81eed413a8e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -923,6 +923,10 @@ end: 0 The query was cached and user was sent the result. -1 The query was cached but we didn't have rights to use it. No error is sent to the client yet. + + NOTE + This method requires that sql points to allocated memory of size: + tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; */ int From ab39c1baf1d73fe54e9b96874f3f3cb8b4a67201 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 17:55:28 -0400 Subject: [PATCH 26/80] Fix ctype_cp932 test to be deterministic on different machines. mysql-test/r/ctype_cp932.result: Update results to make them deterministic mysql-test/t/ctype_cp932.test: Updated test to be deterministic on all machines --- mysql-test/r/ctype_cp932.result | 13 ++++++++----- mysql-test/t/ctype_cp932.test | 4 +++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ctype_cp932.result b/mysql-test/r/ctype_cp932.result index 85e317481d1..0711f251a07 100644 --- a/mysql-test/r/ctype_cp932.result +++ b/mysql-test/r/ctype_cp932.result @@ -8576,16 +8576,19 @@ FC4B DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; +RESET MASTER; CREATE TABLE t1(f1 blob); PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; SET @var1= x'8300'; EXECUTE stmt1 USING @var1; -SHOW BINLOG EVENTS FROM 27642; +SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000001 27642 Query 1 27642 use `test`; CREATE TABLE t1(f1 blob) -master-bin.000001 27701 Query 1 27701 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8 -master-bin.000001 27837 User var 1 27837 @`var1`=_binary 0x8300 COLLATE binary -master-bin.000001 27876 Query 1 27876 use `test`; INSERT INTO t1 VALUES(@'var1') +master-bin.000001 # Start 1 # Server ver: 4.1.15-debug-log, Binlog ver: 3 +master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8 +master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(f1 blob) +master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8 +master-bin.000001 # User var 1 # @`var1`=_binary 0x8300 COLLATE binary +master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES(@'var1') SELECT HEX(f1) FROM t1; HEX(f1) 8300 diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test index 34bf7965248..8f471ebb979 100644 --- a/mysql-test/t/ctype_cp932.test +++ b/mysql-test/t/ctype_cp932.test @@ -403,6 +403,7 @@ DROP TABLE t3; # Test prepared statement with 0x8300 sequence in parameter while # running with cp932 client character set. +RESET MASTER; CREATE TABLE t1(f1 blob); PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; SET @var1= x'8300'; @@ -417,7 +418,8 @@ SET @var1= x'8300'; # code (and I have used it to test the fix) until there is some way to # exercise this code from mysql-test-run. EXECUTE stmt1 USING @var1; -SHOW BINLOG EVENTS FROM 27642; +--replace_column 2 # 5 # +SHOW BINLOG EVENTS; SELECT HEX(f1) FROM t1; DROP table t1; # end test for bug#11338 From 05001e750404612a9dbd7f8398fe2f9d851285dd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Aug 2005 15:51:40 -0700 Subject: [PATCH 27/80] Fix cases where SLEEP() calls would get optimized away or cached. (Bug #12689) mysql-test/r/func_misc.result: Add new results mysql-test/t/func_misc.test: Add new regression test. sql/item_create.cc: When SLEEP() is used, mark the statement as uncacheable. sql/item_func.h: Flag SLEEP() as not constant, and set RAND_TABLE_BIT so that it is always evaluated. --- mysql-test/r/func_misc.result | 24 ++++++++++++++++++++++++ mysql-test/t/func_misc.test | 23 +++++++++++++++++++++++ sql/item_create.cc | 1 + sql/item_func.h | 6 ++++++ 4 files changed, 54 insertions(+) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 670b8754e30..36666fc827d 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -70,3 +70,27 @@ select timediff(b, a) >= '00:00:03' from t1; timediff(b, a) >= '00:00:03' 1 drop table t1; +set global query_cache_size=1355776; +create table t1 (a int); +insert into t1 values (1),(1),(1); +create table t2 (a datetime default null, b datetime default null); +insert into t2 set a = now(); +select a from t1 where sleep(1); +a +update t2 set b = now() where b is null; +insert into t2 set a = now(); +select a from t1 where sleep(a); +a +update t2 set b = now() where b is null; +insert into t2 set a = now(); +select a from t1 where sleep(1); +a +update t2 set b = now() where b is null; +select timediff(b, a) >= '00:00:03' from t2; +timediff(b, a) >= '00:00:03' +1 +1 +1 +drop table t2; +drop table t1; +set global query_cache_size=default; diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index f4cbacb93bb..4a618a56483 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -55,3 +55,26 @@ select sleep(3); update t1 set b = now(); select timediff(b, a) >= '00:00:03' from t1; drop table t1; + +# +# Bug #12689: SLEEP() gets incorrectly cached/optimized-away +# +set global query_cache_size=1355776; +create table t1 (a int); +insert into t1 values (1),(1),(1); +create table t2 (a datetime default null, b datetime default null); +insert into t2 set a = now(); +select a from t1 where sleep(1); +update t2 set b = now() where b is null; +insert into t2 set a = now(); +select a from t1 where sleep(a); +update t2 set b = now() where b is null; +insert into t2 set a = now(); +select a from t1 where sleep(1); +update t2 set b = now() where b is null; +select timediff(b, a) >= '00:00:03' from t2; +drop table t2; +drop table t1; +set global query_cache_size=default; + +# End of 5.0 tests diff --git a/sql/item_create.cc b/sql/item_create.cc index 8798bf889fc..77476e41d0b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -356,6 +356,7 @@ Item *create_func_sha(Item* a) Item *create_func_sleep(Item* a) { + current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new Item_func_sleep(a); } diff --git a/sql/item_func.h b/sql/item_func.h index 1f25b762b70..384cb486f7c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -893,7 +893,13 @@ class Item_func_sleep :public Item_int_func { public: Item_func_sleep(Item *a) :Item_int_func(a) {} + bool const_item() const { return 0; } const char *func_name() const { return "sleep"; } + void update_used_tables() + { + Item_int_func::update_used_tables(); + used_tables_cache|= RAND_TABLE_BIT; + } longlong val_int(); }; From 3eda70b270e2d24e6b4bd6662ddc0b2172b47b67 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 20 Aug 2005 11:00:00 +0300 Subject: [PATCH 28/80] Fixes during review of new pushed code Fixed new bug when running a SP without a default database mysql-test/r/information_schema.result: Added test to cover changes made in default handling mysql-test/r/sp-security.result: Added test when executing SP without a default database mysql-test/t/information_schema.test: Added test to cover changes made in default handling mysql-test/t/sp-security.test: Added test when executing SP without a default database sql/item_strfunc.cc: Removed wrong push sql/mysqld.cc: Indentation fix sql/sql_base.cc: Use share->db instead of share->table_cache_key Remove assert that can never fail (because of test in previous row) sql/sql_db.cc: Allow empty database name when called from SP (To allow on run without a default database) sql/sql_parse.cc: Added comment sql/sql_show.cc: Indentation fixes Simplified code by checking for 'wrong' condition first and doing continue instead of going down one level Simplified precision and decimal handling --- mysql-test/r/information_schema.result | 4 + mysql-test/r/sp-security.result | 2 + mysql-test/t/information_schema.test | 1 + mysql-test/t/sp-security.test | 6 + sql/item_strfunc.cc | 3 - sql/mysqld.cc | 3 +- sql/sql_base.cc | 13 +- sql/sql_db.cc | 22 +- sql/sql_parse.cc | 7 +- sql/sql_show.cc | 379 +++++++++++++------------ 10 files changed, 233 insertions(+), 207 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 64e2434521e..7ec2fcdd453 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -966,4 +966,8 @@ column_name column_default a NULL b NULL use test; +show columns from t1; +Field Type Null Key Default Extra +a int(11) NO +b int(11) YES NULL drop table t1; diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index d78f5fc36ea..eb2e2ce334e 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -245,6 +245,8 @@ end// grant usage on *.* to mysqltest_1@localhost; call mysqltest_1.p1(); ERROR 42000: execute command denied to user 'mysqltest_1'@'localhost' for routine 'mysqltest_1.p1' +call mysqltest_1.p1(); +ERROR 42000: execute command denied to user 'mysqltest_1'@'localhost' for routine 'mysqltest_1.p1' drop procedure mysqltest_1.p1; drop database mysqltest_1; revoke usage on *.* from mysqltest_1@localhost; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 03810447299..04d53828035 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -649,4 +649,5 @@ use information_schema; select column_name, column_default from columns where table_schema='test' and table_name='t1'; use test; +show columns from t1; drop table t1; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index c7c7ef20a5b..6f1332f80d5 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -397,6 +397,12 @@ connection n1; --error 1370 call mysqltest_1.p1(); disconnect n1; +# Test also without a current database +connect (n2,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK); +connection n2; +--error 1370 +call mysqltest_1.p1(); +disconnect n2; connection default; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1e1cc123e60..094a0c56319 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2176,9 +2176,6 @@ void Item_func_lpad::fix_length_and_dec() { ulonglong length= ((ulonglong) args[1]->val_int() * collation.collation->mbmaxlen); - /*a comment before (merged) */ - length= max((ulonglong)args[0]->max_length, length); - /*a comment after */ if (length >= MAX_BLOB_WIDTH) { length= MAX_BLOB_WIDTH; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e58fa669130..5288fc04294 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -730,7 +730,8 @@ static void close_connections(void) DBUG_PRINT("quit",("Informing thread %ld that it's time to die", tmp->thread_id)); /* We skip slave threads on this first loop through. */ - if (tmp->slave_thread) continue; + if (tmp->slave_thread) + continue; tmp->killed= THD::KILL_CONNECTION; if (tmp->mysys_var) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 98ce12eb7de..f9193d38c98 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -150,14 +150,10 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) DBUG_ASSERT(share->table_name != 0); if ((!share->table_name)) // To be removed continue; // Shouldn't happen - if (db && my_strcasecmp(system_charset_info, db, share->table_cache_key)) + if (db && my_strcasecmp(system_charset_info, db, share->db)) + continue; + if (wild && wild_compare(share->table_name,wild,0)) continue; - - if (wild) - { - if (wild_compare(share->table_name,wild,0)) - continue; - } /* Check if user has SELECT privilege for any column in the table */ table_list.db= (char*) share->db; @@ -3803,7 +3799,6 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, if (cur_left_neighbor && cur_table_ref->outer_join & JOIN_TYPE_RIGHT) { - DBUG_ASSERT(cur_table_ref); /* This can happen only for JOIN ... ON. */ DBUG_ASSERT(table_ref->nested_join->join_list.elements == 2); swap_variables(TABLE_LIST*, cur_left_neighbor, cur_table_ref); @@ -3813,7 +3808,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, store_top_level_join_columns(thd, cur_table_ref, cur_left_neighbor, cur_right_neighbor)) DBUG_RETURN(TRUE); - cur_right_neighbor= cur_table_ref; + cur_right_neighbor= cur_table_ref; } } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 67fc1053774..874dfd5f975 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -998,7 +998,7 @@ err: mysql_change_db() thd Thread handler name Databasename - no_access_check True= don't do access check + no_access_check True don't do access check. In this case name may be "" DESCRIPTION Becasue the database name may have been given directly from the @@ -1025,14 +1025,22 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) char *dbname=my_strdup((char*) name,MYF(MY_WME)); char path[FN_REFLEN]; HA_CREATE_INFO create; - bool schema_db= 0; + bool system_db= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; #endif DBUG_ENTER("mysql_change_db"); + DBUG_PRINT("enter",("name: '%s'",name)); + /* dbname can only be NULL if malloc failed */ if (!dbname || !(db_length= strlen(dbname))) { + if (no_access_check && dbname) + { + /* Called from SP when orignal database was not set */ + system_db= 1; + goto end; + } x_free(dbname); /* purecov: inspected */ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */ @@ -1047,7 +1055,7 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) DBUG_PRINT("info",("Use database: %s", dbname)); if (!my_strcasecmp(system_charset_info, dbname, information_schema_name.str)) { - schema_db= 1; + system_db= 1; #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access= SELECT_ACL; #endif @@ -1055,13 +1063,15 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!no_access_check) { + if (!no_access_check) + { if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | thd->master_access); - if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + if (!(db_access & DB_ACLS) && (!grant_option || + check_grant_db(thd,dbname))) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), thd->priv_user, @@ -1094,7 +1104,7 @@ end: if (!no_access_check) thd->db_access=db_access; #endif - if (schema_db) + if (system_db) { thd->db_charset= system_charset_info; thd->variables.collation_database= system_charset_info; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2ba82954319..4fc01d99d22 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -238,7 +238,8 @@ end: /* - Check if user exist and password supplied is correct. + Check if user exist and password supplied is correct. + SYNOPSIS check_user() thd thread handle, thd->{host,user,ip} are used @@ -273,6 +274,10 @@ int check_user(THD *thd, enum enum_server_command command, /* Change database if necessary */ if (db && db[0]) { + /* + thd->db is saved in caller and needs to be freed by caller if this + function returns 0 + */ thd->db= 0; thd->db_length= 0; if (mysql_change_db(thd, db, FALSE)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index b06f1d683dd..767981702db 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -620,7 +620,7 @@ static const char *require_quotes(const char *name, uint name_length) uint length; const char *end= name + name_length; - for ( ; name < end ; name++) + for (; name < end ; name++) { uchar chr= (uchar) *name; length= my_mbcharlen(system_charset_info, chr); @@ -1908,7 +1908,7 @@ int make_db_list(THD *thd, List *files, int schema_tables_add(THD *thd, List *files, const char *wild) { ST_SCHEMA_TABLE *tmp_schema_table= schema_tables; - for ( ; tmp_schema_table->table_name; tmp_schema_table++) + for (; tmp_schema_table->table_name; tmp_schema_table++) { if (tmp_schema_table->hidden) continue; @@ -2365,7 +2365,13 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, LEX *lex= thd->lex; const char *wild= lex->wild ? lex->wild->ptr() : NullS; CHARSET_INFO *cs= system_charset_info; + TABLE *show_table; + handler *file; + Field **ptr,*field; + int count; + uint base_name_length, file_name_length; DBUG_ENTER("get_schema_column_record"); + if (res) { if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS) @@ -2382,189 +2388,187 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, DBUG_RETURN(res); } - TABLE *show_table= tables->table; - handler *file= show_table->file; + show_table= tables->table; + file= show_table->file; + count= 0; file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); restore_record(show_table, s->default_values); - Field **ptr,*field; - int count= 0; + base_name_length= strlen(base_name); + file_name_length= strlen(file_name); + for (ptr=show_table->field; (field= *ptr) ; ptr++) { - if (!wild || !wild[0] || - !wild_case_compare(system_charset_info, field->field_name,wild)) - { - const char *tmp_buff; - byte *pos; - bool is_blob; - uint flags=field->flags; - char tmp[MAX_FIELD_WIDTH]; - char tmp1[MAX_FIELD_WIDTH]; - String type(tmp,sizeof(tmp), system_charset_info); - char *end= tmp; - count++; - restore_record(table, s->default_values); + const char *tmp_buff; + byte *pos; + bool is_blob; + uint flags=field->flags; + char tmp[MAX_FIELD_WIDTH]; + char tmp1[MAX_FIELD_WIDTH]; + String type(tmp,sizeof(tmp), system_charset_info); + char *end; + int decimals, field_length; + + if (wild && wild[0] && + wild_case_compare(system_charset_info, field->field_name,wild)) + continue; + + flags= field->flags; + count++; + /* Get default row, with all NULL fields set to NULL */ + restore_record(table, s->default_values); #ifndef NO_EMBEDDED_ACCESS_CHECKS - uint col_access; - check_access(thd,SELECT_ACL | EXTRA_ACL, base_name, - &tables->grant.privilege, 0, 0); - col_access= get_column_grant(thd, &tables->grant, - base_name, file_name, - field->field_name) & COL_ACLS; - if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS && - !tables->schema_table && !col_access) - continue; - for (uint bitnr=0; col_access ; col_access>>=1,bitnr++) + uint col_access; + check_access(thd,SELECT_ACL | EXTRA_ACL, base_name, + &tables->grant.privilege, 0, 0); + col_access= get_column_grant(thd, &tables->grant, + base_name, file_name, + field->field_name) & COL_ACLS; + if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS && + !tables->schema_table && !col_access) + continue; + end= tmp; + for (uint bitnr=0; col_access ; col_access>>=1,bitnr++) + { + if (col_access & 1) { - if (col_access & 1) - { - *end++=','; - end=strmov(end,grant_types.type_names[bitnr]); - } + *end++=','; + end=strmov(end,grant_types.type_names[bitnr]); } - if (tables->schema_table) // any user has 'select' privilege on all - // I_S table columns - table->field[17]->store(grant_types.type_names[0], - strlen(grant_types.type_names[0]), cs); - else - table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); - -#else - *end= 0; -#endif - table->field[1]->store(base_name, strlen(base_name), cs); - table->field[2]->store(file_name, strlen(file_name), cs); - table->field[3]->store(field->field_name, strlen(field->field_name), - cs); - table->field[4]->store((longlong) count); - field->sql_type(type); - table->field[14]->store(type.ptr(), type.length(), cs); - tmp_buff= strchr(type.ptr(), '('); - table->field[7]->store(type.ptr(), - (tmp_buff ? tmp_buff - type.ptr() : - type.length()), cs); - if (show_table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_UN_FIELD) - { - table->field[5]->store("CURRENT_TIMESTAMP", 17, cs); - table->field[5]->set_notnull(); - } - else if (field->unireg_check != Field::NEXT_NUMBER && - !field->is_null() && - !(field->flags & NO_DEFAULT_VALUE_FLAG)) - { - String def(tmp1,sizeof(tmp1), cs); - type.set(tmp, sizeof(tmp), field->charset()); - field->val_str(&type); - uint dummy_errors; - def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors); - table->field[5]->store(def.ptr(), def.length(), def.charset()); - table->field[5]->set_notnull(); - } - else if (field->unireg_check == Field::NEXT_NUMBER || - lex->orig_sql_command != SQLCOM_SHOW_FIELDS || - field->maybe_null()) - table->field[5]->set_null(); // Null as default - else - { - table->field[5]->store("",0, cs); - table->field[5]->set_notnull(); - } - pos=(byte*) ((flags & NOT_NULL_FLAG) && - field->type() != FIELD_TYPE_TIMESTAMP ? - "NO" : "YES"); - table->field[6]->store((const char*) pos, - strlen((const char*) pos), cs); - is_blob= (field->type() == FIELD_TYPE_BLOB); - if (field->has_charset() || is_blob) - { - longlong c_octet_len= is_blob ? (longlong) field->max_length() : - (longlong) field->max_length()/field->charset()->mbmaxlen; - table->field[8]->store(c_octet_len); - table->field[8]->set_notnull(); - table->field[9]->store((longlong) field->max_length()); - table->field[9]->set_notnull(); - } - - { - uint dec =field->decimals(); - switch (field->type()) { - case FIELD_TYPE_NEWDECIMAL: - table->field[10]->store((longlong) - ((Field_new_decimal*)field)->precision); - table->field[10]->set_notnull(); - table->field[11]->store((longlong) field->decimals()); - table->field[11]->set_notnull(); - break; - case FIELD_TYPE_DECIMAL: - { - uint int_part=field->field_length - (dec ? dec + 1 : 0); - table->field[10]->store((longlong) (int_part + dec - 1)); - table->field[10]->set_notnull(); - table->field[11]->store((longlong) field->decimals()); - table->field[11]->set_notnull(); - break; - } - case FIELD_TYPE_TINY: - case FIELD_TYPE_SHORT: - case FIELD_TYPE_LONG: - case FIELD_TYPE_LONGLONG: - case FIELD_TYPE_INT24: - { - table->field[10]->store((longlong) field->max_length() - 1); - table->field[10]->set_notnull(); - table->field[11]->store((longlong) 0); - table->field[11]->set_notnull(); - break; - } - case FIELD_TYPE_BIT: - { - table->field[10]->store((longlong) field->max_length()); - table->field[10]->set_notnull(); - break; - } - case FIELD_TYPE_FLOAT: - case FIELD_TYPE_DOUBLE: - { - table->field[10]->store((longlong) field->field_length); - table->field[10]->set_notnull(); - if (dec != NOT_FIXED_DEC) - { - table->field[11]->store((longlong) dec); - table->field[11]->set_notnull(); - } - break; - } - default: - break; - } - } - if (field->has_charset()) - { - pos=(byte*) field->charset()->csname; - table->field[12]->store((const char*) pos, - strlen((const char*) pos), cs); - table->field[12]->set_notnull(); - pos=(byte*) field->charset()->name; - table->field[13]->store((const char*) pos, - strlen((const char*) pos), cs); - table->field[13]->set_notnull(); - } - pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : - (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : - (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); - table->field[15]->store((const char*) pos, - strlen((const char*) pos), cs); - end= tmp; - if (field->unireg_check == Field::NEXT_NUMBER) - end=strmov(tmp,"auto_increment"); - table->field[16]->store(tmp, (uint) (end-tmp), cs); - - end=tmp; - table->field[18]->store(field->comment.str, field->comment.length, cs); - if (schema_table_store_record(thd, table)) - DBUG_RETURN(1); } + if (tables->schema_table) // any user has 'select' privilege on all + // I_S table columns + table->field[17]->store(grant_types.type_names[0], + strlen(grant_types.type_names[0]), cs); + else + table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); + +#endif + table->field[1]->store(base_name, base_name_length, cs); + table->field[2]->store(file_name, file_name_length, cs); + table->field[3]->store(field->field_name, strlen(field->field_name), + cs); + table->field[4]->store((longlong) count); + field->sql_type(type); + table->field[14]->store(type.ptr(), type.length(), cs); + tmp_buff= strchr(type.ptr(), '('); + table->field[7]->store(type.ptr(), + (tmp_buff ? tmp_buff - type.ptr() : + type.length()), cs); + if (show_table->timestamp_field == field && + field->unireg_check != Field::TIMESTAMP_UN_FIELD) + { + table->field[5]->store("CURRENT_TIMESTAMP", 17, cs); + table->field[5]->set_notnull(); + } + else if (field->unireg_check != Field::NEXT_NUMBER && + !field->is_null() && + !(field->flags & NO_DEFAULT_VALUE_FLAG)) + { + String def(tmp1,sizeof(tmp1), cs); + type.set(tmp, sizeof(tmp), field->charset()); + field->val_str(&type); + uint dummy_errors; + def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors); + table->field[5]->store(def.ptr(), def.length(), def.charset()); + table->field[5]->set_notnull(); + } + else if (field->unireg_check == Field::NEXT_NUMBER || + lex->orig_sql_command != SQLCOM_SHOW_FIELDS || + field->maybe_null()) + table->field[5]->set_null(); // Null as default + else + { + table->field[5]->store("",0, cs); + table->field[5]->set_notnull(); + } + pos=(byte*) ((flags & NOT_NULL_FLAG) && + field->type() != FIELD_TYPE_TIMESTAMP ? + "NO" : "YES"); + table->field[6]->store((const char*) pos, + strlen((const char*) pos), cs); + is_blob= (field->type() == FIELD_TYPE_BLOB); + if (field->has_charset() || is_blob) + { + longlong c_octet_len= is_blob ? (longlong) field->max_length() : + (longlong) field->max_length()/field->charset()->mbmaxlen; + table->field[8]->store(c_octet_len); + table->field[8]->set_notnull(); + table->field[9]->store((longlong) field->max_length()); + table->field[9]->set_notnull(); + } + + /* + Calculate field_length and decimals. + They are set to -1 if they should not be set (we should return NULL) + */ + + decimals= field->decimals(); + switch (field->type()) { + case FIELD_TYPE_NEWDECIMAL: + field_length= ((Field_new_decimal*) field)->precision; + break; + case FIELD_TYPE_DECIMAL: + field_length= field->field_length - (decimals ? 2 : 1); + break; + case FIELD_TYPE_TINY: + case FIELD_TYPE_SHORT: + case FIELD_TYPE_LONG: + case FIELD_TYPE_LONGLONG: + case FIELD_TYPE_INT24: + field_length= field->max_length() - 1; + break; + case FIELD_TYPE_BIT: + field_length= field->max_length(); + decimals= -1; // return NULL + break; + case FIELD_TYPE_FLOAT: + case FIELD_TYPE_DOUBLE: + field_length= field->field_length; + if (decimals == NOT_FIXED_DEC) + decimals= -1; // return NULL + break; + default: + field_length= decimals= -1; + break; + } + + if (field_length >= 0) + { + table->field[10]->store((longlong) field_length); + table->field[10]->set_notnull(); + } + if (decimals >= 0) + { + table->field[11]->store((longlong) decimals); + table->field[11]->set_notnull(); + } + + if (field->has_charset()) + { + pos=(byte*) field->charset()->csname; + table->field[12]->store((const char*) pos, + strlen((const char*) pos), cs); + table->field[12]->set_notnull(); + pos=(byte*) field->charset()->name; + table->field[13]->store((const char*) pos, + strlen((const char*) pos), cs); + table->field[13]->set_notnull(); + } + pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : + (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : + (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); + table->field[15]->store((const char*) pos, + strlen((const char*) pos), cs); + + end= tmp; + if (field->unireg_check == Field::NEXT_NUMBER) + end=strmov(tmp,"auto_increment"); + table->field[16]->store(tmp, (uint) (end-tmp), cs); + + table->field[18]->store(field->comment.str, field->comment.length, cs); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); } DBUG_RETURN(0); } @@ -2577,7 +2581,8 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; TABLE *table= tables->table; CHARSET_INFO *scs= system_charset_info; - for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ ) + + for (cs= all_charsets ; cs < all_charsets+255 ; cs++) { CHARSET_INFO *tmp_cs= cs[0]; if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && @@ -2585,12 +2590,12 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) !(wild && wild[0] && wild_case_compare(scs, tmp_cs->csname,wild))) { + const char *comment; restore_record(table, s->default_values); table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs); table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs); - table->field[2]->store(tmp_cs->comment ? tmp_cs->comment : "", - strlen(tmp_cs->comment ? tmp_cs->comment : ""), - scs); + comment= tmp_cs->comment ? tmp_cs->comment : ""; + table->field[2]->store(comment, strlen(comment), scs); table->field[3]->store((longlong) tmp_cs->mbmaxlen); if (schema_table_store_record(thd, table)) return 1; @@ -2606,14 +2611,14 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; TABLE *table= tables->table; CHARSET_INFO *scs= system_charset_info; - for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ ) + for (cs= all_charsets ; cs < all_charsets+255 ; cs++ ) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; - for ( cl= all_charsets; cl < all_charsets+255 ;cl ++) + for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || @@ -2646,14 +2651,14 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) CHARSET_INFO **cs; TABLE *table= tables->table; CHARSET_INFO *scs= system_charset_info; - for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ ) + for (cs= all_charsets ; cs < all_charsets+255 ; cs++ ) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; - for ( cl= all_charsets; cl < all_charsets+255 ;cl ++) + for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || @@ -3258,7 +3263,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) { ST_SCHEMA_TABLE *schema_table= schema_tables; - for ( ; schema_table->table_name; schema_table++) + for (; schema_table->table_name; schema_table++) { if (!my_strcasecmp(system_charset_info, schema_table->table_name, @@ -3299,7 +3304,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("create_schema_table"); - for ( ; fields_info->field_name; fields_info++) + for (; fields_info->field_name; fields_info++) { switch (fields_info->field_type) { case MYSQL_TYPE_LONG: @@ -3368,7 +3373,7 @@ int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= schema_table->fields_info; Name_resolution_context *context= &thd->lex->select_lex.context; - for ( ; field_info->field_name; field_info++) + for (; field_info->field_name; field_info++) { if (field_info->old_name) { From ad8c5c9df914366314cd01832521c818b997a21e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 20 Aug 2005 10:07:46 -0400 Subject: [PATCH 29/80] Bug #12460 Table Full On 64 bit platforms the changed statement doesn't work so making sure that the larger value is first and using subtraction is a quick and backwards-compatible fix of this line. --- heap/hp_delete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/heap/hp_delete.c b/heap/hp_delete.c index 9cf8b8936b6..90e537081d3 100644 --- a/heap/hp_delete.c +++ b/heap/hp_delete.c @@ -80,7 +80,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, custom_arg.search_flag= SEARCH_SAME; old_allocated= keyinfo->rb_tree.allocated; res= tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg); - info->s->index_length+= (keyinfo->rb_tree.allocated-old_allocated); + info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated); return res; } From 72340a481a4706674780b898b81a1850a6654d3d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 01:13:37 +0300 Subject: [PATCH 30/80] Cleanup during review of new pushed code include/my_global.h: Safer macros to avoid possible overflows sql/item_cmpfunc.cc: Simple optimization sql/sp_head.cc: Indentation fixes Remove not needed "else" levels Added error checking for 'new' Simpler reseting of thd->spcont in execute_procedure sql/sql_base.cc: Faster new sql/sql_lex.cc: Use 'TRUE' instead of 'true' sql/sql_parse.cc: Faster new sql/sql_view.cc: No need to set 'tables' as it's not used sql/table.cc: Simpler DBUG_ASSERT() --- include/my_global.h | 14 +-- sql/item_cmpfunc.cc | 3 +- sql/sp_head.cc | 262 ++++++++++++++++++++++---------------------- sql/sql_base.cc | 2 +- sql/sql_lex.cc | 2 +- sql/sql_parse.cc | 2 +- sql/sql_view.cc | 2 +- sql/table.cc | 14 +-- 8 files changed, 152 insertions(+), 149 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 2546dde754d..95d0b983b72 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -933,10 +933,10 @@ typedef char bool; /* Ordinary boolean values 0 1 */ (ABSTIME).ts_nsec=0; \ } #define set_timespec_nsec(ABSTIME,NSEC) \ -{\ - ulonglong now= my_getsystime(); \ - (ABSTIME).ts_sec= (now / ULL(10000000)) + (NSEC / ULL(1000000000)); \ - (ABSTIME).ts_nsec= (now % ULL(10000000)) * 100 + (NSEC % ULL(1000000000)); \ +{ \ + ulonglong now= my_getsystime() + (NSEC/100); \ + (ABSTIME).ts_sec= (now / ULL(10000000)); \ + (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ } #else #define set_timespec(ABSTIME,SEC) \ @@ -948,9 +948,9 @@ typedef char bool; /* Ordinary boolean values 0 1 */ } #define set_timespec_nsec(ABSTIME,NSEC) \ {\ - ulonglong now= my_getsystime(); \ - (ABSTIME).tv_sec= (now / ULL(10000000)) + (NSEC / ULL(1000000000)); \ - (ABSTIME).tv_nsec= (now % ULL(10000000)) * 100 + (NSEC % ULL(1000000000)); \ + ulonglong now= my_getsystime() + (NSEC/100); \ + (ABSTIME).tv_sec= (now / ULL(10000000)); \ + (ABSTIME).tv_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ } #endif /* HAVE_TIMESPEC_TS_SEC */ #endif /* set_timespec */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1bae5f1c9af..9443a2949d8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -630,7 +630,7 @@ int Arg_comparator::compare_row() owner->null_value= 0; res= 0; // continue comparison (maybe we will meet explicit difference) } - if (res) + else if (res) return res; } if (was_null) @@ -645,6 +645,7 @@ int Arg_comparator::compare_row() return 0; } + int Arg_comparator::compare_e_row() { (*a)->bring_value(); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f119ef1ec22..ebcbfb67fc8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -127,16 +127,17 @@ sp_prepare_func_item(THD* thd, Item **it_addr) /* Macro to switch arena in sp_eval_func_item */ -#define CREATE_ON_CALLERS_ARENA(new_command, condition, backup_arena) do\ - {\ - if (condition) \ - thd->set_n_backup_item_arena(thd->spcont->callers_arena,\ - backup_arena);\ - new_command;\ - if (condition)\ - thd->restore_backup_item_arena(thd->spcont->callers_arena,\ - &backup_current_arena);\ - } while(0) +#define CREATE_ON_CALLERS_ARENA(new_command, condition, backup_arena) \ + do \ + { \ + if (condition) \ + thd->set_n_backup_item_arena(thd->spcont->callers_arena, \ + backup_arena); \ + new_command; \ + if (condition) \ + thd->restore_backup_item_arena(thd->spcont->callers_arena, \ + &backup_current_arena); \ + } while(0) /* Evaluate an item and store it in the returned item @@ -174,88 +175,82 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, DBUG_RETURN(NULL); } - /* QQ How do we do this? Is there some better way? */ - if (type == MYSQL_TYPE_NULL) - goto return_null_item; - switch (sp_map_result_type(type)) { case INT_RESULT: - { - longlong i= it->val_int(); + { + longlong i= it->val_int(); - if (it->null_value) - { - DBUG_PRINT("info", ("INT_RESULT: null")); - goto return_null_item; - } - else - { - DBUG_PRINT("info", ("INT_RESULT: %d", i)); - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_int(i), - use_callers_arena, &backup_current_arena); - } - break; + if (it->null_value) + { + DBUG_PRINT("info", ("INT_RESULT: null")); + goto return_null_item; } + DBUG_PRINT("info", ("INT_RESULT: %d", i)); + CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_int(i), + use_callers_arena, &backup_current_arena); + break; + } case REAL_RESULT: - { - double d= it->val_real(); + { + double d= it->val_real(); + uint8 decimals; + uint32 max_length; - if (it->null_value) - { - DBUG_PRINT("info", ("REAL_RESULT: null")); - goto return_null_item; - } - else - { - /* There's some difference between Item::new_item() and the - * constructor; the former crashes, the latter works... weird. */ - uint8 decimals= it->decimals; - uint32 max_length= it->max_length; - DBUG_PRINT("info", ("REAL_RESULT: %g", d)); - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_float(d), - use_callers_arena, &backup_current_arena); - it->decimals= decimals; - it->max_length= max_length; - } - break; + if (it->null_value) + { + DBUG_PRINT("info", ("REAL_RESULT: null")); + goto return_null_item; } + + /* + There's some difference between Item::new_item() and the + constructor; the former crashes, the latter works... weird. + */ + decimals= it->decimals; + max_length= it->max_length; + DBUG_PRINT("info", ("REAL_RESULT: %g", d)); + CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_float(d), + use_callers_arena, &backup_current_arena); + it->decimals= decimals; + it->max_length= max_length; + break; + } case DECIMAL_RESULT: - { - my_decimal value, *val= it->val_decimal(&value); - if (it->null_value) - goto return_null_item; - else - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_decimal(val), - use_callers_arena, &backup_current_arena); + { + my_decimal value, *val= it->val_decimal(&value); + if (it->null_value) + goto return_null_item; + CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_decimal(val), + use_callers_arena, &backup_current_arena); #ifndef DBUG_OFF - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; - DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val))); -#endif - break; - } - case STRING_RESULT: { - char buffer[MAX_FIELD_WIDTH]; - String tmp(buffer, sizeof(buffer), it->collation.collation); - String *s= it->val_str(&tmp); - - if (it->null_value) - { - DBUG_PRINT("info", ("default result: null")); - goto return_null_item; - } - else - { - DBUG_PRINT("info",("default result: %*s", - s->length(), s->c_ptr_quick())); - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) - Item_string(thd->strmake(s->ptr(), - s->length()), s->length(), - it->collation.collation), - use_callers_arena, &backup_current_arena); - } - break; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + DBUG_PRINT("info", ("DECIMAL_RESULT: %s", + dbug_decimal_as_string(dbug_buff, val))); +#endif } + break; + } + case STRING_RESULT: + { + char buffer[MAX_FIELD_WIDTH]; + String tmp(buffer, sizeof(buffer), it->collation.collation); + String *s= it->val_str(&tmp); + + if (type == MYSQL_TYPE_NULL || it->null_value) + { + DBUG_PRINT("info", ("STRING_RESULT: null")); + goto return_null_item; + } + DBUG_PRINT("info",("STRING_RESULT: %*s", + s->length(), s->c_ptr_quick())); + CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) + Item_string(thd->strmake(s->ptr(), + s->length()), s->length(), + it->collation.collation), + use_callers_arena, &backup_current_arena); + break; + } case ROW_RESULT: default: DBUG_ASSERT(0); @@ -574,13 +569,10 @@ sp_head::destroy() /* - * This is only used for result fields from functions (both during - * fix_length_and_dec() and evaluation). - * - * Since the current mem_root during a will be freed and the result - * field will be used by the caller, we have to put it in the caller's - * or main mem_root. - */ + This is only used for result fields from functions (both during + fix_length_and_dec() and evaluation). +*/ + Field * sp_head::make_field(uint max_length, const char *name, TABLE *dummy) { @@ -817,47 +809,49 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; uint i; - int ret; + Item_null *nit; + int ret= -1; // Assume error if (argcount != params) { /* - Need to use my_printf_error here, or it will not terminate the + Need to use my_error here, or it will not terminate the invoking query properly. */ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "FUNCTION", m_qname.str, params, argcount); - DBUG_RETURN(-1); + goto end; } // QQ Should have some error checking here? (types, etc...) - nctx= new sp_rcontext(csize, hmax, cmax); + if (!(nctx= new sp_rcontext(csize, hmax, cmax))) + goto end; for (i= 0 ; i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL, FALSE); - if (it) - nctx->push_item(it); - else - { - DBUG_RETURN(-1); - } + if (!it) + goto end; // EOM error + nctx->push_item(it); } + /* The rest of the frame are local variables which are all IN. Default all variables to null (those with default clauses will be set by an set instruction). */ + + nit= NULL; // Re-use this, and only create if needed + for (; i < csize ; i++) { - Item_null *nit= NULL; // Re-use this, and only create if needed - for (; i < csize ; i++) + if (! nit) { - if (! nit) - nit= new Item_null(); - nctx->push_item(nit); + if (!(nit= new Item_null())) + DBUG_RETURN(-1); } + nctx->push_item(nit); } thd->spcont= nctx; @@ -878,14 +872,15 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) } nctx->pop_all_cursors(); // To avoid memory leaks after an error - delete nctx; + delete nctx; // Doesn't do anything thd->spcont= octx; +end: DBUG_RETURN(ret); } -static Item_func_get_user_var * -item_is_user_var(Item *it) + +static Item_func_get_user_var *item_is_user_var(Item *it) { if (it->type() == Item::FUNC_ITEM) { @@ -897,19 +892,18 @@ item_is_user_var(Item *it) return NULL; } -int -sp_head::execute_procedure(THD *thd, List *args) + +int sp_head::execute_procedure(THD *thd, List *args) { - DBUG_ENTER("sp_head::execute_procedure"); - DBUG_PRINT("info", ("procedure %s", m_name.str)); int ret= 0; uint csize = m_pcont->max_pvars(); uint params = m_pcont->current_pvars(); uint hmax = m_pcont->max_handlers(); uint cmax = m_pcont->max_cursors(); - sp_rcontext *octx = thd->spcont; + sp_rcontext *save_spcont, *octx; sp_rcontext *nctx = NULL; - my_bool is_tmp_octx = FALSE; // True if we have allocated a temporary octx + DBUG_ENTER("sp_head::execute_procedure"); + DBUG_PRINT("info", ("procedure %s", m_name.str)); if (args->elements != params) { @@ -918,17 +912,22 @@ sp_head::execute_procedure(THD *thd, List *args) DBUG_RETURN(-1); } + save_spcont= octx= thd->spcont; if (! octx) { // Create a temporary old context - octx= new sp_rcontext(csize, hmax, cmax); - is_tmp_octx= TRUE; + if (!(octx= new sp_rcontext(csize, hmax, cmax))) + DBUG_RETURN(-1); thd->spcont= octx; /* set callers_arena to thd, for upper-level function to work */ thd->spcont->callers_arena= thd; } - nctx= new sp_rcontext(csize, hmax, cmax); + if (!(nctx= new sp_rcontext(csize, hmax, cmax))) + { + thd->spcont= save_spcont; + DBUG_RETURN(-1); + } if (csize > 0 || hmax > 0 || cmax > 0) { @@ -937,7 +936,6 @@ sp_head::execute_procedure(THD *thd, List *args) List_iterator li(*args); Item *it; - /* Evaluate SP arguments (i.e. get the values passed as parameters) */ // QQ: Should do type checking? DBUG_PRINT("info",(" %.*s: eval args", m_name.length, m_name.str)); @@ -959,20 +957,25 @@ sp_head::execute_procedure(THD *thd, List *args) if (pvar->mode == sp_param_out) { if (! nit) - nit= new Item_null(); + { + if (!(nit= new Item_null())) + { + ret= -1; + break; + } + } nctx->push_item(nit); // OUT } else { Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type, NULL, FALSE); - if (it2) - nctx->push_item(it2); // IN or INOUT - else + if (!it2) { ret= -1; // Eval failed break; } + nctx->push_item(it2); // IN or INOUT } } } @@ -994,7 +997,13 @@ sp_head::execute_procedure(THD *thd, List *args) for (; i < csize ; i++) { if (! nit) - nit= new Item_null(); + { + if (!(nit= new Item_null())) + { + ret= -1; + break; + } + } nctx->push_item(nit); } } @@ -1090,15 +1099,12 @@ sp_head::execute_procedure(THD *thd, List *args) } } - if (is_tmp_octx) - { - delete octx; /* call destructor */ - octx= NULL; - } + if (!save_spcont) + delete octx; // Does nothing nctx->pop_all_cursors(); // To avoid memory leaks after an error - delete nctx; - thd->spcont= octx; + delete nctx; // Does nothing + thd->spcont= save_spcont; DBUG_RETURN(ret); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 23b8dae24fb..186d5984dcd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3363,7 +3363,7 @@ static bool set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref) { Name_resolution_context *context; - if (!(context= new Name_resolution_context)) + if (!(context= new (thd->mem_root) Name_resolution_context)) return TRUE; context->init(); context->first_name_resolution_table= diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6ede870a7fb..031d133a40c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1520,7 +1520,7 @@ void st_select_lex_unit::print(String *str) if (union_all) str->append("all ", 4); else if (union_distinct == sl) - union_all= true; + union_all= TRUE; } if (sl->braces) str->append('('); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 619a84e185e..31d0f3eb675 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6420,7 +6420,7 @@ Name_resolution_context * make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op) { Name_resolution_context *on_context; - if (!(on_context= new Name_resolution_context)) + if (!(on_context= new (thd->mem_root) Name_resolution_context)) return NULL; on_context->init(); on_context->first_name_resolution_table= diff --git a/sql/sql_view.cc b/sql/sql_view.cc index af21b43e5c9..dcada0c0780 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -310,7 +310,7 @@ bool mysql_create_view(THD *thd, open_and_lock_tables can change the value of tables, e.g. it may happen if before the function call tables was equal to 0. */ - for (tbl= tables= lex->query_tables; tbl; tbl= tbl->next_global) + for (tbl= lex->query_tables; tbl; tbl= tbl->next_global) { /* is this table temporary and is not view? */ if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && diff --git a/sql/table.cc b/sql/table.cc index beecd6442e8..e84f8adc32f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2518,12 +2518,9 @@ void Field_iterator_natural_join::set(TABLE_LIST *table_ref) void Field_iterator_natural_join::next() { cur_column_ref= (*column_ref_it)++; - DBUG_ASSERT(cur_column_ref ? - (cur_column_ref->table_field ? - cur_column_ref->table_ref->table == - cur_column_ref->table_field->table : - TRUE) : - TRUE); + DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || + cur_column_ref->table_ref->table == + cur_column_ref->table_field->table); } @@ -2695,9 +2692,8 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col); } - DBUG_ASSERT(nj_col->table_field ? - nj_col->table_ref->table == nj_col->table_field->table : - TRUE); + DBUG_ASSERT(!nj_col->table_field || + nj_col->table_ref->table == nj_col->table_field->table); return nj_col; } From 9349800946806ab53cb133deae743f11bcf8eb09 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 10:59:25 +0200 Subject: [PATCH 31/80] bug#12220 - ndb - node recovery with charsets LQH computes incorrect hash values during NR (as it doesn't concider charsets) Solution: make LQH compute correct hash :-) 1) move xfrm_key into SimulatedBlock so that there's _one_ impl. 2) make TC, ACC, LQH use same impl. ndb/include/kernel/AttributeDescriptor.hpp: Make SimulatedBlock use AttributeDescriptor (to xfrm) ndb/src/kernel/blocks/dbacc/Dbacc.hpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dbacc/DbaccInit.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dbacc/DbaccMain.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dblqh/Dblqh.hpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dbtc/Dbtc.hpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/vm/SimulatedBlock.cpp: Move xfrm handling into SimulatedBlock ndb/src/kernel/vm/SimulatedBlock.hpp: Move xfrm handling into SimulatedBlock --- ndb/include/kernel/AttributeDescriptor.hpp | 3 +- ndb/src/kernel/blocks/dbacc/Dbacc.hpp | 8 -- ndb/src/kernel/blocks/dbacc/DbaccInit.cpp | 1 - ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 129 ++---------------- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 68 ++++++---- ndb/src/kernel/blocks/dblqh/Dblqh.hpp | 2 +- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 59 +++------ ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 5 - ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 145 +++------------------ ndb/src/kernel/vm/SimulatedBlock.cpp | 115 ++++++++++++++++ ndb/src/kernel/vm/SimulatedBlock.hpp | 20 +++ 11 files changed, 237 insertions(+), 318 deletions(-) diff --git a/ndb/include/kernel/AttributeDescriptor.hpp b/ndb/include/kernel/AttributeDescriptor.hpp index af28e777213..2fe7c9f0973 100644 --- a/ndb/include/kernel/AttributeDescriptor.hpp +++ b/ndb/include/kernel/AttributeDescriptor.hpp @@ -23,7 +23,8 @@ class AttributeDescriptor { friend class Dbacc; friend class Dbtup; friend class Dbtux; - + friend class SimulatedBlock; + private: static void setType(Uint32 &, Uint32 type); static void setSize(Uint32 &, Uint32 size); diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp index a2d6fe4d64a..8800388e96c 100644 --- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp +++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp @@ -851,13 +851,6 @@ struct Tabrec { Uint32 fragptrholder[MAX_FRAG_PER_NODE]; Uint32 tabUserPtr; BlockReference tabUserRef; - - Uint8 noOfKeyAttr; - Uint8 hasCharAttr; - struct KeyAttr { - Uint32 attributeDescriptor; - CHARSET_INFO* charsetInfo; - } keyAttr[MAX_ATTRIBUTES_IN_INDEX]; }; typedef Ptr TabrecPtr; @@ -903,7 +896,6 @@ private: void execACCKEYREQ(Signal* signal); void execACCSEIZEREQ(Signal* signal); void execACCFRAGREQ(Signal* signal); - void execTC_SCHVERREQ(Signal* signal); void execACC_SRREQ(Signal* signal); void execNEXT_SCANREQ(Signal* signal); void execACC_ABORTREQ(Signal* signal); diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp index 90839163a72..d4ff20e4c43 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp @@ -179,7 +179,6 @@ Dbacc::Dbacc(const class Configuration & conf): addRecSignal(GSN_ACCKEYREQ, &Dbacc::execACCKEYREQ); addRecSignal(GSN_ACCSEIZEREQ, &Dbacc::execACCSEIZEREQ); addRecSignal(GSN_ACCFRAGREQ, &Dbacc::execACCFRAGREQ); - addRecSignal(GSN_TC_SCHVERREQ, &Dbacc::execTC_SCHVERREQ); addRecSignal(GSN_ACC_SRREQ, &Dbacc::execACC_SRREQ); addRecSignal(GSN_NEXT_SCANREQ, &Dbacc::execNEXT_SCANREQ); addRecSignal(GSN_ACC_ABORTREQ, &Dbacc::execACC_ABORTREQ); diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index aefd2612151..37b6825cbd2 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -28,7 +28,8 @@ #include #include #include -#include +#include + // TO_DO_RONM is a label for comments on what needs to be improved in future versions // when more time is given. @@ -1037,12 +1038,6 @@ void Dbacc::initialiseTableRec(Signal* signal) tabptr.p->fragholder[i] = RNIL; tabptr.p->fragptrholder[i] = RNIL; }//for - tabptr.p->noOfKeyAttr = 0; - tabptr.p->hasCharAttr = 0; - for (Uint32 k = 0; k < MAX_ATTRIBUTES_IN_INDEX; k++) { - tabptr.p->keyAttr[k].attributeDescriptor = 0; - tabptr.p->keyAttr[k].charsetInfo = 0; - } }//for }//Dbacc::initialiseTableRec() @@ -1172,8 +1167,8 @@ void Dbacc::execACCFRAGREQ(Signal* signal) Uint32 userPtr = req->userPtr; BlockReference retRef = req->userRef; rootfragrecptr.p->rootState = ACTIVEROOT; - AccFragConf * const conf = (AccFragConf*)&signal->theData[0]; + AccFragConf * const conf = (AccFragConf*)&signal->theData[0]; conf->userPtr = userPtr; conf->rootFragPtr = rootfragrecptr.i; conf->fragId[0] = rootfragrecptr.p->fragmentid[0]; @@ -1197,65 +1192,6 @@ void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode) return; }//Dbacc::addFragRefuseEarly() -void -Dbacc::execTC_SCHVERREQ(Signal* signal) -{ - jamEntry(); - if (! assembleFragments(signal)) { - jam(); - return; - } - tabptr.i = signal->theData[0]; - ptrCheckGuard(tabptr, ctablesize, tabrec); - Uint32 noOfKeyAttr = signal->theData[6]; - ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX); - Uint32 hasCharAttr = 0; - - SegmentedSectionPtr s0Ptr; - signal->getSection(s0Ptr, 0); - SectionReader r0(s0Ptr, getSectionSegmentPool()); - Uint32 i = 0; - while (i < noOfKeyAttr) { - jam(); - Uint32 attributeDescriptor = ~0; - Uint32 csNumber = ~0; - if (! r0.getWord(&attributeDescriptor) || - ! r0.getWord(&csNumber)) { - jam(); - break; - } - CHARSET_INFO* cs = 0; - if (csNumber != 0) { - cs = all_charsets[csNumber]; - ndbrequire(cs != 0); - hasCharAttr = 1; - } - tabptr.p->keyAttr[i].attributeDescriptor = attributeDescriptor; - tabptr.p->keyAttr[i].charsetInfo = cs; - i++; - } - ndbrequire(i == noOfKeyAttr); - releaseSections(signal); - - tabptr.p->noOfKeyAttr = noOfKeyAttr; - tabptr.p->hasCharAttr = hasCharAttr; - - // copy char attr flag to each fragment - for (Uint32 i1 = 0; i1 < MAX_FRAG_PER_NODE; i1++) { - jam(); - if (tabptr.p->fragptrholder[i1] != RNIL) { - rootfragrecptr.i = tabptr.p->fragptrholder[i1]; - ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); - for (Uint32 i2 = 0; i2 < 2; i2++) { - fragrecptr.i = rootfragrecptr.p->fragmentptr[i2]; - ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); - fragrecptr.p->hasCharAttr = hasCharAttr; - } - } - } - - // no reply to DICT -} void Dbacc::execDROP_TAB_REQ(Signal* signal){ @@ -1841,55 +1777,14 @@ void Dbacc::execACCKEYREQ(Signal* signal) void Dbacc::xfrmKeyData(Signal* signal) { - tabptr.i = fragrecptr.p->myTableId; - ptrCheckGuard(tabptr, ctablesize, tabrec); - - Uint32 dst[1024 * MAX_XFRM_MULTIPLY]; - Uint32 dstSize = (sizeof(dst) >> 2); + Uint32 table = fragrecptr.p->myTableId; + Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY]; + Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]; Uint32* src = &signal->theData[7]; - const Uint32 noOfKeyAttr = tabptr.p->noOfKeyAttr; - Uint32 dstPos = 0; - Uint32 srcPos = 0; - Uint32 i = 0; - - while (i < noOfKeyAttr) { - const Tabrec::KeyAttr& keyAttr = tabptr.p->keyAttr[i]; - - Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor); - Uint32 srcWords = (srcBytes + 3) / 4; - Uint32 dstWords = ~0; - uchar* dstPtr = (uchar*)&dst[dstPos]; - const uchar* srcPtr = (const uchar*)&src[srcPos]; - CHARSET_INFO* cs = keyAttr.charsetInfo; - - if (cs == 0) { - jam(); - memcpy(dstPtr, srcPtr, srcWords << 2); - dstWords = srcWords; - } else { - jam(); - Uint32 typeId = AttributeDescriptor::getType(keyAttr.attributeDescriptor); - Uint32 lb, len; - bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); - ndbrequire(ok); - Uint32 xmul = cs->strxfrm_multiply; - if (xmul == 0) - xmul = 1; - // see comment in DbtcMain.cpp - Uint32 dstLen = xmul * (srcBytes - lb); - ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); - int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); - ndbrequire(n != -1); - while ((n & 3) != 0) - dstPtr[n++] = 0; - dstWords = (n >> 2); - } - dstPos += dstWords; - srcPos += srcWords; - i++; - } - memcpy(src, dst, dstPos << 2); - operationRecPtr.p->xfrmtupkeylen = dstPos; + Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen); + ndbrequire(len); // 0 means error + memcpy(src, dst, len << 2); + operationRecPtr.p->xfrmtupkeylen = len; } void Dbacc::accIsLockedLab(Signal* signal) @@ -8024,6 +7919,10 @@ void Dbacc::initFragAdd(Signal* signal, Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor; Tmp2 = Tmp1 * Tmp2; regFragPtr.p->slackCheck = Tmp2; + + Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr; + regFragPtr.p->hasCharAttr = hasCharAttr; + }//Dbacc::initFragAdd() void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr) diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 7d036b0e988..2725e7d14fe 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1750,6 +1751,7 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal) c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES); c_tableRecordPool.setSize(tablerecSize); c_tableRecordHash.setSize(tablerecSize); + g_key_descriptor_pool.setSize(tablerecSize); c_triggerRecordPool.setSize(c_maxNoOfTriggers); c_triggerRecordHash.setSize(c_maxNoOfTriggers); c_opRecordPool.setSize(256); // XXX need config params @@ -4450,6 +4452,44 @@ Dbdict::execADD_FRAGREQ(Signal* signal) { sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal, LqhFragReq::SignalLength, JBB); } + + /** + * Create KeyDescriptor + */ + KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i); + new (desc) KeyDescriptor(); + + Uint32 key = 0; + Uint32 tAttr = tabPtr.p->firstAttribute; + while (tAttr != RNIL) + { + jam(); + AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr); + if (aRec->tupleKey) + { + desc->noOfKeyAttr ++; + desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor; + + Uint32 csNumber = (aRec->extPrecision >> 16); + if(csNumber) + { + desc->keyAttr[key].charsetInfo = all_charsets[csNumber]; + ndbrequire(all_charsets[csNumber]); + desc->hasCharAttr = 1; + } + else + { + desc->keyAttr[key].charsetInfo = 0; + } + if(AttributeDescriptor::getDKey(aRec->attributeDescriptor)) + { + desc->noOfDistrKeys ++; + } + key++; + } + tAttr = aRec->nextAttrInTable; + } + ndbrequire(key == tabPtr.p->noOfPrimkey); } void @@ -4644,31 +4684,11 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){ signal->theData[4] = (Uint32)tabPtr.p->tableType; signal->theData[5] = createTabPtr.p->key; signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey; - - Uint32 buf[2 * MAX_ATTRIBUTES_IN_INDEX]; - Uint32 sz = 0; - Uint32 tAttr = tabPtr.p->firstAttribute; - while (tAttr != RNIL) { - jam(); - AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr); - if (aRec->tupleKey) { - buf[sz++] = aRec->attributeDescriptor; - buf[sz++] = (aRec->extPrecision >> 16); // charset number - } - tAttr = aRec->nextAttrInTable; - } - ndbrequire((int)sz == 2 * tabPtr.p->noOfPrimkey); - - LinearSectionPtr lsPtr[3]; - lsPtr[0].p = buf; - lsPtr[0].sz = sz; - // note: ACC does not reply - if (tabPtr.p->isTable() || tabPtr.p->isHashIndex()) - sendSignal(DBACC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB, lsPtr, 1); - sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB, lsPtr, 1); + + sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB); return; } - + ndbrequire(false); } @@ -12342,3 +12362,5 @@ Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table new (&attr) MetaData::Attribute(*attrPtr.p); return 0; } + +CArray g_key_descriptor_pool; diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index fa7e8667e27..ce84834e808 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -2233,7 +2233,7 @@ private: void LQHKEY_abort(Signal* signal, int errortype); void LQHKEY_error(Signal* signal, int errortype); void nextRecordCopy(Signal* signal); - void calculateHash(Signal* signal); + Uint32 calculateHash(Uint32 tableId, const Uint32* src); void continueAfterCheckLcpStopBlocked(Signal* signal); void checkLcpStopBlockedLab(Signal* signal); void sendCommittedTc(Signal* signal, BlockReference atcBlockref); diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 5a35b5eefc0..71b5aaf4163 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -55,6 +55,7 @@ #include #include +#include // Use DEBUG to print messages that should be // seen only when we debug the product @@ -9013,44 +9014,17 @@ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted) /* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */ /* CONNECTIONS TO THE FAILED NODE. */ /*---------------------------------------------------------------------------*/ -void Dblqh::calculateHash(Signal* signal) +Uint32 +Dblqh::calculateHash(Uint32 tableId, const Uint32* src) { - DatabufPtr locDatabufptr; - UintR Ti; - UintR Tdata0; - UintR Tdata1; - UintR Tdata2; - UintR Tdata3; - UintR* Tdata32; - Uint64 Tdata[512]; - - Tdata32 = (UintR*)&Tdata[0]; - - Tdata0 = tcConnectptr.p->tupkeyData[0]; - Tdata1 = tcConnectptr.p->tupkeyData[1]; - Tdata2 = tcConnectptr.p->tupkeyData[2]; - Tdata3 = tcConnectptr.p->tupkeyData[3]; - Tdata32[0] = Tdata0; - Tdata32[1] = Tdata1; - Tdata32[2] = Tdata2; - Tdata32[3] = Tdata3; - locDatabufptr.i = tcConnectptr.p->firstTupkeybuf; - Ti = 4; - while (locDatabufptr.i != RNIL) { - ptrCheckGuard(locDatabufptr, cdatabufFileSize, databuf); - Tdata0 = locDatabufptr.p->data[0]; - Tdata1 = locDatabufptr.p->data[1]; - Tdata2 = locDatabufptr.p->data[2]; - Tdata3 = locDatabufptr.p->data[3]; - Tdata32[Ti ] = Tdata0; - Tdata32[Ti + 1] = Tdata1; - Tdata32[Ti + 2] = Tdata2; - Tdata32[Ti + 3] = Tdata3; - locDatabufptr.i = locDatabufptr.p->nextDatabuf; - Ti += 4; - }//while - tcConnectptr.p->hashValue = - md5_hash((Uint64*)&Tdata32[0], (UintR)tcConnectptr.p->primKeyLen); + jam(); + Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1]; + Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]; + Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2, + keyPartLen); + ndbrequire(keyLen); + + return md5_hash(Tmp, keyLen); }//Dblqh::calculateHash() /* *************************************** */ @@ -9384,7 +9358,7 @@ void Dblqh::copyTupkeyConfLab(Signal* signal) const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr(); UintR readLength = tupKeyConf->readLength; - + Uint32 tableId = tcConnectptr.p->tableref; scanptr.i = tcConnectptr.p->tcScanRec; c_scanRecordPool.getPtr(scanptr); ScanRecord* scanP = scanptr.p; @@ -9411,7 +9385,14 @@ void Dblqh::copyTupkeyConfLab(Signal* signal) Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp); // Calculate hash (no need to linearies key) - tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len); + if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr) + { + tcConnectptr.p->hashValue = calculateHash(tableId, tmp); + } + else + { + tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len); + } // Move into databuffer to make packLqhkeyreqLab happy memcpy(tcConP->tupkeyData, tmp, 4*4); diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index cd5eedd89ad..bf9f421a0e3 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -962,11 +962,6 @@ public: Uint8 hasCharAttr; Uint8 noOfDistrKeys; - struct KeyAttr { - Uint32 attributeDescriptor; - CHARSET_INFO* charsetInfo; - } keyAttr[MAX_ATTRIBUTES_IN_INDEX]; - bool checkTable(Uint32 schemaVersion) const { return enabled && !dropping && (table_version_major(schemaVersion) == table_version_major(currentSchemaVersion)); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 12f3a278f0e..0ff6d8477b9 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -329,42 +330,16 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal) BlockReference retPtr = signal->theData[5]; Uint32 noOfKeyAttr = signal->theData[6]; ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX); - Uint32 hasCharAttr = 0; - Uint32 noOfDistrKeys = 0; - SegmentedSectionPtr s0Ptr; - signal->getSection(s0Ptr, 0); - SectionReader r0(s0Ptr, getSectionSegmentPool()); - Uint32 i = 0; - while (i < noOfKeyAttr) { - jam(); - Uint32 attributeDescriptor = ~0; - Uint32 csNumber = ~0; - if (! r0.getWord(&attributeDescriptor) || - ! r0.getWord(&csNumber)) { - jam(); - break; - } - CHARSET_INFO* cs = 0; - if (csNumber != 0) { - cs = all_charsets[csNumber]; - ndbrequire(cs != 0); - hasCharAttr = 1; - } - - noOfDistrKeys += AttributeDescriptor::getDKey(attributeDescriptor); - tabptr.p->keyAttr[i].attributeDescriptor = attributeDescriptor; - tabptr.p->keyAttr[i].charsetInfo = cs; - i++; - } - ndbrequire(i == noOfKeyAttr); - releaseSections(signal); + + const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i); + ndbrequire(noOfKeyAttr == desc->noOfKeyAttr); ndbrequire(tabptr.p->enabled == false); tabptr.p->enabled = true; tabptr.p->dropping = false; - tabptr.p->noOfKeyAttr = noOfKeyAttr; - tabptr.p->hasCharAttr = hasCharAttr; - tabptr.p->noOfDistrKeys = noOfDistrKeys; + tabptr.p->noOfKeyAttr = desc->noOfKeyAttr; + tabptr.p->hasCharAttr = desc->hasCharAttr; + tabptr.p->noOfDistrKeys = desc->noOfDistrKeys; signal->theData[0] = tabptr.i; signal->theData[1] = retPtr; @@ -2323,113 +2298,37 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, Uint32 tabPtrI, bool distr) { - Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * 4 * MAX_XFRM_MULTIPLY]; - const Uint32 dstSize = sizeof(Tmp) / 4; + Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY]; const TableRecord* tabPtrP = &tableRecord[tabPtrI]; - const Uint32 noOfKeyAttr = tabPtrP->noOfKeyAttr; - Uint32 noOfDistrKeys = tabPtrP->noOfDistrKeys; const bool hasCharAttr = tabPtrP->hasCharAttr; + const bool hasDistKeys = tabPtrP->noOfDistrKeys > 0; Uint32 *dst = (Uint32*)Tmp; Uint32 dstPos = 0; - Uint32 srcPos = 0; Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]; - if(hasCharAttr){ - Uint32 i = 0; - while (i < noOfKeyAttr) { - const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i]; - - Uint32 srcBytes = - AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor); - Uint32 srcWords = (srcBytes + 3) / 4; - Uint32 dstWords = ~0; - uchar* dstPtr = (uchar*)&dst[dstPos]; - const uchar* srcPtr = (const uchar*)&src[srcPos]; - CHARSET_INFO* cs = keyAttr.charsetInfo; - - if (cs == NULL) { - jam(); - memcpy(dstPtr, srcPtr, srcWords << 2); - dstWords = srcWords; - } else { - jam(); - Uint32 typeId = - AttributeDescriptor::getType(keyAttr.attributeDescriptor); - Uint32 lb, len; - bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); - ndbrequire(ok); - Uint32 xmul = cs->strxfrm_multiply; - if (xmul == 0) - xmul = 1; - /* - * Varchar is really Char. End spaces do not matter. To get - * same hash we blank-pad to maximum length via strnxfrm. - * TODO use MySQL charset-aware hash function instead - */ - Uint32 dstLen = xmul * (srcBytes - lb); - ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); - int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); - ndbrequire(n != -1); - while ((n & 3) != 0) { - dstPtr[n++] = 0; - } - dstWords = (n >> 2); - } - dstPos += dstWords; - srcPos += srcWords; - keyPartLen[i++] = dstWords; - } + Uint32 * keyPartLenPtr; + if(hasCharAttr) + { + keyPartLenPtr = keyPartLen; + dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr); + ndbrequire(dstPos); } else { dst = src; dstPos = srcLen; + keyPartLenPtr = 0; } md5_hash(dstHash, (Uint64*)dst, dstPos); - if(distr && noOfDistrKeys) + if(distr && hasDistKeys) { jam(); - src = dst; - dstPos = 0; - Uint32 i = 0; - if(hasCharAttr) - { - while (i < noOfKeyAttr && noOfDistrKeys) - { - const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i]; - Uint32 len = keyPartLen[i]; - if(AttributeDescriptor::getDKey(keyAttr.attributeDescriptor)) - { - noOfDistrKeys--; - memmove(dst+dstPos, src, len << 2); - dstPos += len; - } - src += len; - i++; - } - } - else - { - while (i < noOfKeyAttr && noOfDistrKeys) - { - const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i]; - Uint32 len = - AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor); - len = (len + 3) / 4; - if(AttributeDescriptor::getDKey(keyAttr.attributeDescriptor)) - { - noOfDistrKeys--; - memmove(dst+dstPos, src, len << 2); - dstPos += len; - } - src += len; - i++; - } - } + Uint32 tmp[4]; - md5_hash(tmp, (Uint64*)dst, dstPos); + Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr); + md5_hash(tmp, (Uint64*)dst, len); dstHash[1] = tmp[1]; } return true; // success @@ -10204,10 +10103,6 @@ void Dbtc::initTable(Signal* signal) tabptr.p->noOfKeyAttr = 0; tabptr.p->hasCharAttr = 0; tabptr.p->noOfDistrKeys = 0; - for (unsigned k = 0; k < MAX_ATTRIBUTES_IN_INDEX; k++) { - tabptr.p->keyAttr[k].attributeDescriptor = 0; - tabptr.p->keyAttr[k].charsetInfo = 0; - } }//for }//Dbtc::initTable() diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index 35c0781a24d..ef9f2c3c716 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -1802,3 +1802,118 @@ SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){ } #endif + +#include "KeyDescriptor.hpp" + +Uint32 +SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src, + Uint32 *dst, Uint32 dstSize, + Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const +{ + const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab); + const Uint32 noOfKeyAttr = desc->noOfKeyAttr; + + Uint32 i = 0; + Uint32 srcPos = 0; + Uint32 dstPos = 0; + while (i < noOfKeyAttr) + { + const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i]; + + Uint32 srcBytes = + AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor); + Uint32 srcWords = (srcBytes + 3) / 4; + Uint32 dstWords = ~0; + uchar* dstPtr = (uchar*)&dst[dstPos]; + const uchar* srcPtr = (const uchar*)&src[srcPos]; + CHARSET_INFO* cs = keyAttr.charsetInfo; + + if (cs == NULL) + { + jam(); + memcpy(dstPtr, srcPtr, srcWords << 2); + dstWords = srcWords; + } + else + { + jam(); + Uint32 typeId = + AttributeDescriptor::getType(keyAttr.attributeDescriptor); + Uint32 lb, len; + bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); + ndbrequire(ok); + Uint32 xmul = cs->strxfrm_multiply; + if (xmul == 0) + xmul = 1; + /* + * Varchar is really Char. End spaces do not matter. To get + * same hash we blank-pad to maximum length via strnxfrm. + * TODO use MySQL charset-aware hash function instead + */ + Uint32 dstLen = xmul * (srcBytes - lb); + ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); + int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); + ndbrequire(n != -1); + while ((n & 3) != 0) + { + dstPtr[n++] = 0; + } + dstWords = (n >> 2); + } + dstPos += dstWords; + srcPos += srcWords; + keyPartLen[i++] = dstWords; + } + + return dstPos; +} + +Uint32 +SimulatedBlock::create_distr_key(Uint32 tableId, + Uint32 *data, + const Uint32 + keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const +{ + const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tableId); + const Uint32 noOfKeyAttr = desc->noOfKeyAttr; + Uint32 noOfDistrKeys = desc->noOfDistrKeys; + + Uint32 *src = data; + Uint32 *dst = data; + Uint32 i = 0; + Uint32 dstPos = 0; + + if(keyPartLen) + { + while (i < noOfKeyAttr && noOfDistrKeys) + { + Uint32 attr = desc->keyAttr[i].attributeDescriptor; + Uint32 len = keyPartLen[i]; + if(AttributeDescriptor::getDKey(attr)) + { + noOfDistrKeys--; + memmove(dst+dstPos, src, len << 2); + dstPos += len; + } + src += len; + i++; + } + } + else + { + while (i < noOfKeyAttr && noOfDistrKeys) + { + Uint32 attr = desc->keyAttr[i].attributeDescriptor; + Uint32 len = AttributeDescriptor::getSizeInWords(attr); + if(AttributeDescriptor::getDKey(attr)) + { + noOfDistrKeys--; + memmove(dst+dstPos, src, len << 2); + dstPos += len; + } + src += len; + i++; + } + } + return dstPos; +} diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp index 787d14ca5cb..50c85a0b274 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -20,11 +20,13 @@ #include #include #include +#include #include "VMSignal.hpp" #include #include #include + #include "pc.hpp" #include #include @@ -385,6 +387,24 @@ protected: */ const NodeInfo & getNodeInfo(NodeId nodeId) const; NodeInfo & setNodeInfo(NodeId); + + /********************** + * Xfrm stuff + */ + + /** + * @return length + */ + Uint32 xfrm_key(Uint32 tab, const Uint32* src, + Uint32 *dst, Uint32 dstLen, + Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const; + + /** + * + */ + Uint32 create_distr_key(Uint32 tableId, + Uint32 *data, + const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const; private: NewVARIABLE* NewVarRef; /* New Base Address Table for block */ From bcb2ed1a2b0e26d64672736b4374dd1889378de3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 11:25:03 +0200 Subject: [PATCH 32/80] ndb - bug#12220 forgott to add KeyDescriptor.hpp ndb/src/kernel/vm/KeyDescriptor.hpp: New BitKeeper file ``ndb/src/kernel/vm/KeyDescriptor.hpp'' --- ndb/src/kernel/vm/KeyDescriptor.hpp | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 ndb/src/kernel/vm/KeyDescriptor.hpp diff --git a/ndb/src/kernel/vm/KeyDescriptor.hpp b/ndb/src/kernel/vm/KeyDescriptor.hpp new file mode 100644 index 00000000000..456d64ce1d8 --- /dev/null +++ b/ndb/src/kernel/vm/KeyDescriptor.hpp @@ -0,0 +1,41 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef KEY_DESCRIPTOR_HPP +#define KEY_DESCRIPTOR_HPP + +#include +#include +#include "CArray.hpp" + +struct KeyDescriptor +{ + KeyDescriptor () { noOfKeyAttr = hasCharAttr = noOfDistrKeys = 0; } + + Uint8 noOfKeyAttr; + Uint8 hasCharAttr; + Uint8 noOfDistrKeys; + Uint8 unused; + struct KeyAttr + { + Uint32 attributeDescriptor; + CHARSET_INFO* charsetInfo; + } keyAttr[MAX_ATTRIBUTES_IN_INDEX]; +}; + +extern CArray g_key_descriptor_pool; + +#endif From 00455bd91c3ac089b7a4465118bf57f5ac62a62b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 11:34:33 +0200 Subject: [PATCH 33/80] ndb - Fix merge error mysql-test/t/ndb_config.test: Fix merge error --- mysql-test/t/ndb_config.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test index 66287bf6d29..ab3063af672 100644 --- a/mysql-test/t/ndb_config.test +++ b/mysql-test/t/ndb_config.test @@ -1,4 +1,5 @@ -- source include/have_ndb.inc +-- source include/ndb_default_cluster.inc -- source include/not_embedded.inc --exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=type,nodeid,host 2> /dev/null From 8fc308b873ae6fb7deea59c9a8328c4b0026c2c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 12:48:01 +0200 Subject: [PATCH 34/80] Ensure that a failing test does not stop testing or the whole RPM build process. --- support-files/mysql.spec.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index b563972e08a..af9abd2fce1 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -308,7 +308,7 @@ BuildMySQL "--enable-shared \ --with-comment=\"MySQL Community Edition - Max (GPL)\" \ --with-server-suffix='-Max'" -make test +make test-force || true # Save mysqld-max mv sql/mysqld sql/mysqld-max @@ -359,7 +359,7 @@ BuildMySQL "--disable-shared \ --without-openssl" nm --numeric-sort sql/mysqld > sql/mysqld.sym -make test +make test-force || true %install RBR=$RPM_BUILD_ROOT From aebf2e49c8f2b6834c7bfcb0fe397a71f2084265 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 17:04:55 +0300 Subject: [PATCH 35/80] Test case for BUG#6558 - Views: create fails with JOIN ... USING The bug is non-view specific, and it resulted from incorrect name resolution of natural join result columns. The bug is fixed by WL#2486. mysql-test/r/select.result: Added test case for BUG#6558 mysql-test/t/select.test: Added test case for BUG#6558 --- mysql-test/r/select.result | 10 ++++++++++ mysql-test/t/select.test | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ed075c8a6ad..63ed0d187f0 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2765,3 +2765,13 @@ f1 f2 f3 f4 2 2 2 one 2 2 2 two drop table t1,t2; +create table t1 (empnum smallint, grp int); +create table t2 (empnum int, name char(5)); +insert into t1 values(1,1); +insert into t2 values(1,'bob'); +create view v1 as select * from t2 inner join t1 using (empnum); +select * from v1; +empnum name grp +1 bob 1 +drop table t1,t2; +drop view v1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index b8975749fd6..fc0df8fb8b5 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2358,3 +2358,16 @@ insert into t1 values (" 2", 2); insert into t2 values (" 2", " one "),(" 2", " two "); select * from t1 left join t2 on f1 = f3; drop table t1,t2; + +# +# Bug #6558 Views: CREATE VIEW fails with JOIN ... USING +# + +create table t1 (empnum smallint, grp int); +create table t2 (empnum int, name char(5)); +insert into t1 values(1,1); +insert into t2 values(1,'bob'); +create view v1 as select * from t2 inner join t1 using (empnum); +select * from v1; +drop table t1,t2; +drop view v1; From 9f70b1758eb1aa6f6f2e12ef31a7a55aa98af98d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 17:34:08 +0300 Subject: [PATCH 36/80] Test case for BUG#10646 The bug itself is fixed by WL #2486. mysql-test/r/select.result: Test for BUG#10646 mysql-test/t/select.test: Test for BUG#10646 --- mysql-test/r/select.result | 5 +++++ mysql-test/t/select.test | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 63ed0d187f0..64946b88a41 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2775,3 +2775,8 @@ empnum name grp 1 bob 1 drop table t1,t2; drop view v1; +create table t1 (pk int primary key, b int); +create table t2 (pk int primary key, c int); +select pk from t1 inner join t2 using (pk); +pk +drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index fc0df8fb8b5..373aa73eec0 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2371,3 +2371,13 @@ create view v1 as select * from t2 inner join t1 using (empnum); select * from v1; drop table t1,t2; drop view v1; + +# +# Bug #10646 Columns included in the join between two tables are ambigious +# in the select +# + +create table t1 (pk int primary key, b int); +create table t2 (pk int primary key, c int); +select pk from t1 inner join t2 using (pk); +drop table t1,t2; From d6c3f0f4b6529a1389b11c3c62dc3506f1ea514d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 18:59:47 +0400 Subject: [PATCH 37/80] Fix a -ansi -pedantic compile failure. --- server-tools/instance-manager/instance.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index ee37690d40a..cbcfee0c7ef 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -42,7 +42,7 @@ public: void kill_instance(int signo); int is_crashed(); void set_crash_flag_n_wake_all(); - Instance_map *Instance::get_map(); + Instance_map *get_map(); public: enum { DEFAULT_SHUTDOWN_DELAY= 35 }; From 0b4ec2fb427b242b2522f16b870933e10ce1a716 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 19:23:01 +0400 Subject: [PATCH 38/80] Add a comment about I_List<> copy constructor. sql/sql_list.h: Add a comment. --- sql/sql_list.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/sql_list.h b/sql/sql_list.h index 09c01931c38..e4a34cc0aa1 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -426,9 +426,14 @@ struct ilink template class I_List_iterator; +/* + WARNING: copy constructor of this class does not create a usable + copy, as its members may point at each other. +*/ + class base_ilist { - public: +public: struct ilink *first,last; inline void empty() { first= &last; last.prev= &first; } base_ilist() { empty(); } From 2e44fbb01bc9bf75790dc267ec5c5f64e2b6d63c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 19:56:36 +0300 Subject: [PATCH 39/80] Don't write first even that contains server version --- mysql-test/r/ctype_cp932.result | 3 +-- mysql-test/t/ctype_cp932.test | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ctype_cp932.result b/mysql-test/r/ctype_cp932.result index f677af7db76..08206a91b7b 100755 --- a/mysql-test/r/ctype_cp932.result +++ b/mysql-test/r/ctype_cp932.result @@ -11320,9 +11320,8 @@ CREATE TABLE t1(f1 blob); PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; SET @var1= x'8300'; EXECUTE stmt1 USING @var1; -SHOW BINLOG EVENTS; +SHOW BINLOG EVENTS FROM 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 4 Format_desc 1 98 Server ver: 5.0.12-beta-debug-log, Binlog ver: 4 master-bin.000001 98 Query 1 185 use `test`; CREATE TABLE t1(f1 blob) master-bin.000001 185 User var 1 224 @`var1`=_binary 0x8300 COLLATE binary master-bin.000001 224 Query 1 317 use `test`; INSERT INTO t1 VALUES(@'var1') diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test index c41ee489a37..3d630311b3a 100644 --- a/mysql-test/t/ctype_cp932.test +++ b/mysql-test/t/ctype_cp932.test @@ -415,7 +415,7 @@ SET @var1= x'8300'; # code (and I have used it to test the fix) until there is some way to # exercise this code from mysql-test-run. EXECUTE stmt1 USING @var1; -SHOW BINLOG EVENTS; +SHOW BINLOG EVENTS FROM 98; SELECT HEX(f1) FROM t1; DROP table t1; # end test for bug#11338 From b2344cd5f9229e831975e531b30769a6c6ac037e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 22:13:56 +0200 Subject: [PATCH 40/80] added file missing from release to EXTRA_DIST list (bug# 12733) --- BUILD/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 27a42cdca16..45c1aaa1a76 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = FINISH.sh \ SETUP.sh \ + autorun.sh \ check-cpu \ compile-alpha \ compile-alpha-ccc \ From d40acb4d3f34a99a3d700021b0ae89b623e0ff94 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 15:48:50 -0700 Subject: [PATCH 41/80] Use the hostname with which the user authenticated when determining which user to update with 'SET PASSWORD = ...'. (Bug #12302) mysql-test/r/grant2.result: Add new results mysql-test/t/grant2.test: Add new tests sql/set_var.cc: Pass priv_host into check_change_password(). sql/sql_acl.cc: Add exact flag for find_acl_user, so we can specify that we want an exact match on the hostname. --- mysql-test/r/grant2.result | 26 ++++++++++++++++++++++++++ mysql-test/t/grant2.test | 38 ++++++++++++++++++++++++++++++++++++++ sql/set_var.cc | 13 ++++++++++++- sql/sql_acl.cc | 19 +++++++++++-------- 4 files changed, 87 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index ada205f6f23..8bd39b0225e 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -94,5 +94,31 @@ i 2 3 REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; drop table mysqltest_1.t1; +grant all on mysqltest_1.* to mysqltest_1@'127.0.0.1'; +select current_user(); +current_user() +mysqltest_1@127.0.0.1 +set password = password('changed'); +select host, length(password) from mysql.user where user like 'mysqltest\_1'; +host length(password) +127.0.0.1 41 +revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.1'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; +grant all on mysqltest_1.* to mysqltest_1@'127.0.0.0/255.0.0.0'; +select current_user(); +current_user() +mysqltest_1@127.0.0.0/255.0.0.0 +set password = password('changed'); +select host, length(password) from mysql.user where user like 'mysqltest\_1'; +host length(password) +127.0.0.0/255.0.0.0 41 +revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.0/255.0.0.0'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; drop database mysqltest_1; +set password = password("changed"); +ERROR 42000: Access denied for user ''@'localhost' to database 'mysql' diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index f347869d9ec..e3e733a50c3 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -122,7 +122,45 @@ select * from t1; disconnect n1; connection default; REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; drop table mysqltest_1.t1; + +# +# Bug #12302: 'SET PASSWORD = ...' didn't work if connecting hostname != +# hostname the current user is authenticated as. Note that a test for this +# was also added to the test above. +# +grant all on mysqltest_1.* to mysqltest_1@'127.0.0.1'; +connect (b12302,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,); +connection b12302; +select current_user(); +set password = password('changed'); +disconnect b12302; +connection default; +select host, length(password) from mysql.user where user like 'mysqltest\_1'; +revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.1'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; +grant all on mysqltest_1.* to mysqltest_1@'127.0.0.0/255.0.0.0'; +connect (b12302_2,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,); +connection b12302_2; +select current_user(); +set password = password('changed'); +disconnect b12302_2; +connection default; +select host, length(password) from mysql.user where user like 'mysqltest\_1'; +revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.0/255.0.0.0'; +delete from mysql.user where user like 'mysqltest\_1'; +flush privileges; drop database mysqltest_1; +# But anonymous users can't change their password +connect (n5,localhost,test,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connection n5; +--error 1044 +set password = password("changed"); +disconnect n5; +connection default; + # End of 4.1 tests diff --git a/sql/set_var.cc b/sql/set_var.cc index f7700d18607..1b66b68b349 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2944,7 +2944,18 @@ int set_var_password::check(THD *thd) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!user->host.str) - user->host.str= (char*) thd->host_or_ip; + { + if (thd->priv_host != 0) + { + user->host.str= (char *) thd->priv_host; + user->host.length= strlen(thd->priv_host); + } + else + { + user->host.str= (char *)"%"; + user->host.length= 1; + } + } /* Returns 1 as the function sends error to client */ return check_change_password(thd, user->host.str, user->user.str, password, strlen(password)) ? 1 : 0; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d191da32189..813754ad937 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -67,7 +67,8 @@ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0); static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b); static ulong get_sort(uint count,...); static void init_check_host(void); -static ACL_USER *find_acl_user(const char *host, const char *user); +static ACL_USER *find_acl_user(const char *host, const char *user, + my_bool exact); static bool update_user_table(THD *thd, const char *host, const char *user, const char *new_password, uint new_password_len); static void update_hostname(acl_host_and_ip *host, const char *hostname); @@ -1188,7 +1189,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(&my_charset_latin1, host, thd->priv_host))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) return(1); @@ -1240,7 +1241,7 @@ bool change_password(THD *thd, const char *host, const char *user, VOID(pthread_mutex_lock(&acl_cache->lock)); ACL_USER *acl_user; - if (!(acl_user= find_acl_user(host, user))) + if (!(acl_user= find_acl_user(host, user, TRUE))) { VOID(pthread_mutex_unlock(&acl_cache->lock)); send_error(thd, ER_PASSWORD_NO_MATCH); @@ -1282,7 +1283,7 @@ bool change_password(THD *thd, const char *host, const char *user, */ static ACL_USER * -find_acl_user(const char *host, const char *user) +find_acl_user(const char *host, const char *user, my_bool exact) { DBUG_ENTER("find_acl_user"); DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user)); @@ -1298,7 +1299,9 @@ find_acl_user(const char *host, const char *user) if (!acl_user->user && !user[0] || acl_user->user && !strcmp(user,acl_user->user)) { - if (compare_hostname(&acl_user->host,host,host)) + if (exact ? !my_strcasecmp(&my_charset_latin1, host, + acl_user->host.hostname) : + compare_hostname(&acl_user->host,host,host)) { DBUG_RETURN(acl_user); } @@ -1689,7 +1692,7 @@ static int replace_db_table(TABLE *table, const char *db, } /* Check if there is such a user in user table in memory? */ - if (!find_acl_user(combo.host.str,combo.user.str)) + if (!find_acl_user(combo.host.str,combo.user.str, FALSE)) { my_error(ER_PASSWORD_NO_MATCH,MYF(0)); DBUG_RETURN(-1); @@ -2151,7 +2154,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, The following should always succeed as new users are created before this function is called! */ - if (!find_acl_user(combo.host.str,combo.user.str)) + if (!find_acl_user(combo.host.str,combo.user.str, FALSE)) { my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */ @@ -3448,7 +3451,7 @@ void get_privilege_desc(char *to, uint max_length, ulong access) void get_mqh(const char *user, const char *host, USER_CONN *uc) { ACL_USER *acl_user; - if (initialized && (acl_user= find_acl_user(host,user))) + if (initialized && (acl_user= find_acl_user(host,user, FALSE))) uc->user_resources= acl_user->user_resource; else bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); From 57f575b2e4f4ae3726518cf55b1c7ee07f717409 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 17:32:02 -0700 Subject: [PATCH 42/80] sql_show.cc: Database name was set incorrectly for any show command that used sunqueries in its where condition. information_schema.test, information_schema.result: Added a test case for bug #12636. mysql-test/r/information_schema.result: Added a test case for bug #12636. mysql-test/t/information_schema.test: Added a test case for bug #12636. sql/sql_show.cc: Database name was set incorrectly for any show command that used sunqueries in its where condition. --- mysql-test/r/information_schema.result | 8 ++++++++ mysql-test/t/information_schema.test | 15 +++++++++++++++ sql/sql_show.cc | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 3f1e94c9e5f..b1c5f8de7dc 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -967,3 +967,11 @@ a NULL b NULL use test; drop table t1; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +SHOW TABLE STATUS FROM test +WHERE name IN ( SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE'); +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 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 03810447299..5410885a404 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -650,3 +650,18 @@ select column_name, column_default from columns where table_schema='test' and table_name='t1'; use test; drop table t1; + +# +# Bug #12636: SHOW TABLE STATUS with where condition containing a subquery +# over information schema +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); + +--replace_column 8 # 12 # 13 # +SHOW TABLE STATUS FROM test + WHERE name IN ( SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE'); + +DROP TABLE t1,t2 diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 958971d65f1..f140e20ca83 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1705,7 +1705,7 @@ void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values) case SQLCOM_SHOW_TABLES: case SQLCOM_SHOW_TABLE_STATUS: case SQLCOM_SHOW_TRIGGERS: - index_field_values->db_value= lex->current_select->db; + index_field_values->db_value= lex->select_lex.db; index_field_values->table_value= wild; break; default: From a267fd22f1919f3d9f02c64d5c4a6d59c61679af Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Aug 2005 18:07:42 -0700 Subject: [PATCH 43/80] Reorder server startup so that network startup is done after storage engine startup. (Bug #11707) sql/mysqld.cc: Reorder network startup to come after all other initialization, particularly storage engine startup which can take a long time. --- sql/mysqld.cc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2e38ec98c08..bae6b08bfed 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1257,7 +1257,7 @@ static void set_root(const char *path) #endif } -static void server_init(void) +static void network_init(void) { struct sockaddr_in IPaddr; #ifdef HAVE_SYS_UN_H @@ -1319,16 +1319,6 @@ static void server_init(void) } } - if ((user_info= check_user(mysqld_user))) - { -#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) - if (locked_in_memory) // getuid() == 0 here - set_effective_user(user_info); - else -#endif - set_user(mysqld_user, user_info); - } - #ifdef __NT__ /* create named pipe */ if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap && @@ -3039,7 +3029,17 @@ int main(int argc, char **argv) mysql_data_home= mysql_data_home_buff; mysql_data_home[0]=FN_CURLIB; // all paths are relative from here mysql_data_home[1]=0; - server_init(); + + if ((user_info= check_user(mysqld_user))) + { +#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) + if (locked_in_memory) // getuid() == 0 here + set_effective_user(user_info); + else +#endif + set_user(mysqld_user, user_info); + } + if (opt_bin_log && !server_id) { @@ -3064,6 +3064,8 @@ we force server id to 2, but this MySQL server will not act as a slave."); if (init_server_components()) exit(1); + network_init(); + #ifdef __WIN__ if (!opt_console) { From 8803c688b536086588e5f3139f05386a942d62cf Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 11:50:24 +0200 Subject: [PATCH 44/80] enabled make of ndb_redo_log_reader --- ndb/src/kernel/blocks/dblqh/Makefile.am | 8 ++++++-- .../blocks/dblqh/redoLogReader/redoLogFileReader.cpp | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ndb/src/kernel/blocks/dblqh/Makefile.am b/ndb/src/kernel/blocks/dblqh/Makefile.am index 854860b269c..bb8efe8c5b8 100644 --- a/ndb/src/kernel/blocks/dblqh/Makefile.am +++ b/ndb/src/kernel/blocks/dblqh/Makefile.am @@ -1,12 +1,16 @@ -#SUBDIRS = redoLogReader - noinst_LIBRARIES = libdblqh.a +EXTRA_PROGRAMS = ndbd_redo_log_reader libdblqh_a_SOURCES = DblqhInit.cpp DblqhMain.cpp +ndbd_redo_log_reader_SOURCES = redoLogReader/records.cpp redoLogReader/redoLogFileReader.cpp include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_kernel.mk.am +LDADD += \ + $(top_builddir)/ndb/src/common/util/libgeneral.la \ + $(top_builddir)/ndb/src/common/portlib/libportlib.la + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp index 540df7b507e..67e59c48ea6 100644 --- a/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp +++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp @@ -40,7 +40,7 @@ Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords); void readArguments(int argc, const char** argv); void doExit(); -FILE * f; +FILE * f= 0; char fileName[256]; bool thePrintFlag = true; bool theCheckFlag = true; @@ -458,7 +458,7 @@ void readArguments(int argc, const char** argv) void doExit() { ndbout << "Error in redoLogReader(). Exiting!" << endl; - fclose(f); + if (f) fclose(f); delete [] redoLogPage; exit(RETURN_ERROR); } From a797112c8ae81cb721a58d2d54067e1b54884a3f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 12:16:16 +0200 Subject: [PATCH 45/80] removed ndb grep from configure .in BitKeeper/deleted/.del-Makefile~e0b7d67078f0fae0: Delete: ndb/src/kernel/blocks/dblqh/redoLogReader/Makefile BitKeeper/deleted/.del-Grep.cpp~ad798e9ae519d667: Delete: ndb/src/kernel/blocks/grep/Grep.cpp BitKeeper/deleted/.del-Makefile.am~f73be89578d3b6cc: Delete: ndb/src/kernel/blocks/grep/Makefile.am BitKeeper/deleted/.del-Grep.hpp~b05e3af6cfabe387: Delete: ndb/src/kernel/blocks/grep/Grep.hpp BitKeeper/deleted/.del-GrepInit.cpp~df28ab3a892455fd: Delete: ndb/src/kernel/blocks/grep/GrepInit.cpp BitKeeper/deleted/.del-Makefile~b293ae88e4394490: Delete: ndb/src/kernel/blocks/grep/systab_test/Makefile BitKeeper/deleted/.del-grep_systab_test.cpp~c7305578bec8cb62: Delete: ndb/src/kernel/blocks/grep/systab_test/grep_systab_test.cpp BitKeeper/deleted/.del-testGrep.cpp~2106eb0a6bf2a1b5: Delete: ndb/test/ndbapi/testGrep.cpp --- configure.in | 1 - .../blocks/dblqh/redoLogReader/Makefile | 9 - ndb/src/kernel/blocks/grep/Grep.cpp | 2010 ----------------- ndb/src/kernel/blocks/grep/Grep.hpp | 535 ----- ndb/src/kernel/blocks/grep/GrepInit.cpp | 164 -- ndb/src/kernel/blocks/grep/Makefile.am | 23 - .../kernel/blocks/grep/systab_test/Makefile | 12 - .../grep/systab_test/grep_systab_test.cpp | 138 -- ndb/test/ndbapi/testGrep.cpp | 540 ----- 9 files changed, 3432 deletions(-) delete mode 100644 ndb/src/kernel/blocks/dblqh/redoLogReader/Makefile delete mode 100644 ndb/src/kernel/blocks/grep/Grep.cpp delete mode 100644 ndb/src/kernel/blocks/grep/Grep.hpp delete mode 100644 ndb/src/kernel/blocks/grep/GrepInit.cpp delete mode 100644 ndb/src/kernel/blocks/grep/Makefile.am delete mode 100644 ndb/src/kernel/blocks/grep/systab_test/Makefile delete mode 100644 ndb/src/kernel/blocks/grep/systab_test/grep_systab_test.cpp delete mode 100644 ndb/test/ndbapi/testGrep.cpp diff --git a/configure.in b/configure.in index 9e370dfa680..b9ad38fb59d 100644 --- a/configure.in +++ b/configure.in @@ -3281,7 +3281,6 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl ndb/src/kernel/blocks/backup/Makefile dnl ndb/src/kernel/blocks/dbutil/Makefile dnl ndb/src/kernel/blocks/suma/Makefile dnl - ndb/src/kernel/blocks/grep/Makefile dnl ndb/src/kernel/blocks/dbtux/Makefile dnl ndb/src/kernel/vm/Makefile dnl ndb/src/mgmapi/Makefile dnl diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/Makefile b/ndb/src/kernel/blocks/dblqh/redoLogReader/Makefile deleted file mode 100644 index a89b648de77..00000000000 --- a/ndb/src/kernel/blocks/dblqh/redoLogReader/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include .defs.mk - -BIN_TARGET := redoLogFileReader - -SOURCES := records.cpp redoLogFileReader.cpp - -TYPE := util - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/grep/Grep.cpp b/ndb/src/kernel/blocks/grep/Grep.cpp deleted file mode 100644 index e89361dab06..00000000000 --- a/ndb/src/kernel/blocks/grep/Grep.cpp +++ /dev/null @@ -1,2010 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "Grep.hpp" -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CONTINUEB_DELAY 500 -#define SSREPBLOCKNO 2 -#define PSREPBLOCKNO 2 - -//#define DEBUG_GREP -//#define DEBUG_GREP_SUBSCRIPTION -//#define DEBUG_GREP_TRANSFER -//#define DEBUG_GREP_APPLY -//#define DEBUG_GREP_DELETE - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: STARTUP of GREP Block, etc - * ------------------------------------------------------------------------ - **************************************************************************/ -static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE; -void -Grep::getNodeGroupMembers(Signal* signal) { - jam(); - /** - * Ask DIH for nodeGroupMembers - */ - CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend(); - sd->blockRef = reference(); - sd->requestType = - CheckNodeGroups::Direct | - CheckNodeGroups::GetNodeGroupMembers; - sd->nodeId = getOwnNodeId(); - EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal, - CheckNodeGroups::SignalLength); - jamEntry(); - - c_nodeGroup = sd->output; - c_noNodesInGroup = 0; - for (int i = 0; i < MAX_NDB_NODES; i++) { - if (sd->mask.get(i)) { - if (i == getOwnNodeId()) c_idInNodeGroup = c_noNodesInGroup; - c_nodesInGroup[c_noNodesInGroup] = i; - c_noNodesInGroup++; - } - } - ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup - -#ifdef NODEFAIL_DEBUG - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - ndbout_c ("Grep: NodeGroup %u, me %u, me in group %u, member[%u] %u", - c_nodeGroup, getOwnNodeId(), c_idInNodeGroup, - i, c_nodesInGroup[i]); - } -#endif -} - - -void -Grep::execSTTOR(Signal* signal) -{ - jamEntry(); - const Uint32 startphase = signal->theData[1]; - const Uint32 typeOfStart = signal->theData[7]; - if (startphase == 3) - { - jam(); - signal->theData[0] = reference(); - g_TypeOfStart = typeOfStart; - sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB); - return; - } - if(startphase == 5) { - jam(); - /** - * we don't want any log/meta records comming to use - * until we are done with the recovery. - */ - if (g_TypeOfStart == NodeState::ST_NODE_RESTART) { - jam(); - pspart.m_recoveryMode = true; - getNodeGroupMembers(signal); - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - Uint32 ref =numberToRef(GREP, c_nodesInGroup[i]); - if (ref != reference()) - sendSignal(ref, GSN_GREP_START_ME, signal, - 1 /*SumaStartMe::SignalLength*/, JBB); - } - } else pspart.m_recoveryMode = false; - - } - - if(startphase == 7) { - jam(); - if (g_TypeOfStart == NodeState::ST_NODE_RESTART) { - pspart.m_recoveryMode = false; - } - } - - sendSTTORRY(signal); -} - - -void -Grep::PSPart::execSTART_ME(Signal* signal) -{ - jamEntry(); - GrepStartMe * me =(GrepStartMe*)signal->getDataPtr(); - BlockReference ref = me->senderRef; - GrepAddSubReq* const addReq = (GrepAddSubReq *)signal->getDataPtr(); - - - SubscriptionPtr subPtr; - c_subscriptions.first(c_subPtr); - for(; !c_subPtr.isNull(); c_subscriptions.next(c_subPtr)) { - jam(); - subPtr.i = c_subPtr.curr.i; - subPtr.p = c_subscriptions.getPtr(subPtr.i); - addReq->subscriptionId = subPtr.p->m_subscriptionId; - addReq->subscriptionKey = subPtr.p->m_subscriptionKey; - addReq->subscriberData = subPtr.p->m_subscriberData; - addReq->subscriptionType = subPtr.p->m_subscriptionType; - addReq->senderRef = subPtr.p->m_coordinatorRef; - addReq->subscriberRef =subPtr.p->m_subscriberRef; - - sendSignal(ref, - GSN_GREP_ADD_SUB_REQ, - signal, - GrepAddSubReq::SignalLength, - JBB); - } - - addReq->subscriptionId = 0; - addReq->subscriptionKey = 0; - addReq->subscriberData = 0; - addReq->subscriptionType = 0; - addReq->senderRef = 0; - addReq->subscriberRef = 0; - - sendSignal(ref, - GSN_GREP_ADD_SUB_REQ, - signal, - GrepAddSubReq::SignalLength, - JBB); -} - -void -Grep::PSPart::execGREP_ADD_SUB_REQ(Signal* signal) -{ - jamEntry(); - GrepAddSubReq * const grepReq = (GrepAddSubReq *)signal->getDataPtr(); - const Uint32 subId = grepReq->subscriptionId; - const Uint32 subKey = grepReq->subscriptionKey; - const Uint32 subData = grepReq->subscriberData; - const Uint32 subType = grepReq->subscriptionType; - const Uint32 coordinatorRef = grepReq->senderRef; - - /** - * this is ref to the REP node for this subscription. - */ - const Uint32 subRef = grepReq->subscriberRef; - - if(subId!=0 && subKey!=0) { - jam(); - SubscriptionPtr subPtr; - ndbrequire( c_subscriptionPool.seize(subPtr)); - subPtr.p->m_coordinatorRef = coordinatorRef; - subPtr.p->m_subscriptionId = subId; - subPtr.p->m_subscriptionKey = subKey; - subPtr.p->m_subscriberRef = subRef; - subPtr.p->m_subscriberData = subData; - subPtr.p->m_subscriptionType = subType; - - c_subscriptions.add(subPtr); - } - else { - jam(); - GrepAddSubConf * conf = (GrepAddSubConf *)grepReq; - conf->noOfSub = - c_subscriptionPool.getSize()-c_subscriptionPool.getNoOfFree(); - sendSignal(signal->getSendersBlockRef(), - GSN_GREP_ADD_SUB_CONF, - signal, - GrepAddSubConf::SignalLength, - JBB); - } -} - -void -Grep::PSPart::execGREP_ADD_SUB_REF(Signal* signal) -{ - /** - * @todo fix error stuff - */ -} - -void -Grep::PSPart::execGREP_ADD_SUB_CONF(Signal* signal) -{ - jamEntry(); - GrepAddSubConf* const conf = (GrepAddSubConf *)signal->getDataPtr(); - Uint32 noOfSubscriptions = conf->noOfSub; - Uint32 noOfRestoredSubscriptions = - c_subscriptionPool.getSize()-c_subscriptionPool.getNoOfFree(); - if(noOfSubscriptions!=noOfRestoredSubscriptions) { - jam(); - /** - *@todo send ref signal - */ - ndbrequire(false); - } -} - -void -Grep::execREAD_NODESCONF(Signal* signal) -{ - jamEntry(); - ReadNodesConf * conf = (ReadNodesConf *)signal->getDataPtr(); - -#if 0 - ndbout_c("Grep: Recd READ_NODESCONF"); -#endif - - /****************************** - * Check which REP nodes exist - ******************************/ - Uint32 i; - for (i = 1; i < MAX_NODES; i++) - { - jam(); -#if 0 - ndbout_c("Grep: Found node %d of type %d", i, getNodeInfo(i).getType()); -#endif - if (getNodeInfo(i).getType() == NodeInfo::REP) - { - jam(); - /** - * @todo This should work for more than ONE rep node! - */ - pscoord.m_repRef = numberToRef(PSREPBLOCKNO, i); - pspart.m_repRef = numberToRef(PSREPBLOCKNO, i); -#if 0 - ndbout_c("Grep: REP node %d detected", i); -#endif - } - } - - /***************************** - * Check which DB nodes exist - *****************************/ - m_aliveNodes.clear(); - - Uint32 count = 0; - for(i = 0; iallNodes, i)) - { - jam(); - count++; - - NodePtr node; - ndbrequire(m_nodes.seize(node)); - - node.p->nodeId = i; - if (NodeBitmask::get(conf->inactiveNodes, i)) - { - node.p->alive = 0; - } - else - { - node.p->alive = 1; - m_aliveNodes.set(i); - } - } - } - m_masterNodeId = conf->masterNodeId; - ndbrequire(count == conf->noOfNodes); - sendSTTORRY(signal); -} - -void -Grep::sendSTTORRY(Signal* signal) -{ - signal->theData[0] = 0; - signal->theData[3] = 1; - signal->theData[4] = 3; - signal->theData[5] = 5; - signal->theData[6] = 7; - signal->theData[7] = 255; // No more start phases from missra - sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 8, JBB); -} - -void -Grep::execNDB_STTOR(Signal* signal) -{ - jamEntry(); -} - -void -Grep::execDUMP_STATE_ORD(Signal* signal) -{ - jamEntry(); - //Uint32 tCase = signal->theData[0]; - -#if 0 - if(sscoord.m_repRef == 0) - { - ndbout << "Grep: Recd DUMP signal but has no connection with REP node" - << endl; - return; - } -#endif - - /* - switch (tCase) - { - case 8100: sscoord.grepReq(signal, GrepReq::START_SUBSCR); break; - case 8102: sscoord.grepReq(signal, GrepReq::START_METALOG); break; - case 8104: sscoord.grepReq(signal, GrepReq::START_METASCAN); break; - case 8106: sscoord.grepReq(signal, GrepReq::START_DATALOG); break; - case 8108: sscoord.grepReq(signal, GrepReq::START_DATASCAN); break; - case 8110: sscoord.grepReq(signal, GrepReq::STOP_SUBSCR); break; - case 8500: sscoord.grepReq(signal, GrepReq::REMOVE_BUFFERS); break; - case 8300: sscoord.grepReq(signal, GrepReq::SLOWSTOP); break; - case 8400: sscoord.grepReq(signal, GrepReq::FASTSTOP); break; - case 8600: sscoord.grepReq(signal, GrepReq::CREATE_SUBSCR); break; - case 8700: sscoord.dropTable(signal,(Uint32)signal->theData[1]);break; - default: break; - } - */ -} - -/** - * Signal received when REP node has failed - */ -void -Grep::execAPI_FAILREQ(Signal* signal) -{ - jamEntry(); - //Uint32 failedApiNode = signal->theData[0]; - //BlockReference retRef = signal->theData[1]; - - /** - * @todo We should probably do something smart if the - * PS REP node fails???? /Lars - */ - -#if 0 - ndbout_c("Grep: API_FAILREQ received for API node %d.", failedApiNode); -#endif - - /** - * @note This signal received is NOT allowed to send any CONF - * signal, since this would screw up TC/DICT to API - * "connections". - */ -} - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: GREP Control - * ------------------------------------------------------------------------ - **************************************************************************/ -void -Grep::execGREP_REQ(Signal* signal) -{ - jamEntry(); - - //GrepReq * req = (GrepReq *)signal->getDataPtr(); - - /** - * @todo Fix so that request is redirected to REP Server - * Obsolete? - * Was: sscoord.grepReq(signal, req->request); - */ - ndbout_c("Warning! REP commands can only be executed at REP SERVER prompt!"); -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: NODE STATE HANDLING - * ------------------------------------------------------------------------ - **************************************************************************/ -void -Grep::execNODE_FAILREP(Signal* signal) -{ - jamEntry(); - NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr(); - bool changed = false; - - NodePtr nodePtr; - for(m_nodes.first(nodePtr); nodePtr.i != RNIL; m_nodes.next(nodePtr)) - { - jam(); - if (NodeBitmask::get(rep->theNodes, nodePtr.p->nodeId)) - { - jam(); - - if (nodePtr.p->alive) - { - jam(); - ndbassert(m_aliveNodes.get(nodePtr.p->nodeId)); - changed = true; - } - else - { - ndbassert(!m_aliveNodes.get(nodePtr.p->nodeId)); - } - - nodePtr.p->alive = 0; - m_aliveNodes.clear(nodePtr.p->nodeId); - } - } - - - /** - * Problem: Fix a node failure running a protocol - * - * 1. Coordinator node of a protocol dies - * - Elect a new coordinator - * - send ref to user - * - * 2. Non-coordinator dies. - * - make coordinator aware of this - * so that coordinator does not wait for - * conf from faulty node - * - node recovery will restore the non-coordinator. - * - */ -} - -void -Grep::execINCL_NODEREQ(Signal* signal) -{ - jamEntry(); - - //const Uint32 senderRef = signal->theData[0]; - const Uint32 inclNode = signal->theData[1]; - - NodePtr node; - for(m_nodes.first(node); node.i != RNIL; m_nodes.next(node)) - { - jam(); - const Uint32 nodeId = node.p->nodeId; - if (inclNode == nodeId) { - jam(); - - ndbrequire(node.p->alive == 0); - ndbassert(!m_aliveNodes.get(nodeId)); - - node.p->alive = 1; - m_aliveNodes.set(nodeId); - - break; - } - } - - /** - * @todo: if we include this DIH's got to be prepared, later if needed... - */ -#if 0 - signal->theData[0] = reference(); - - sendSignal(senderRef, GSN_INCL_NODECONF, signal, 1, JBB); -#endif -} - - -/** - * Helper methods - */ -void -Grep::PSCoord::prepareOperationRec(SubCoordinatorPtr subPtr, - BlockReference subscriber, - Uint32 subId, - Uint32 subKey, - Uint32 request) -{ - subPtr.p->m_coordinatorRef = reference(); - subPtr.p->m_subscriberRef = subscriber; - subPtr.p->m_subscriberData = subPtr.i; - subPtr.p->m_subscriptionId = subId; - subPtr.p->m_subscriptionKey = subKey; - subPtr.p->m_outstandingRequest = request; -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: CREATE SUBSCRIPTION ID - * ------------------------------------------------------------------------ - * - * Requests SUMA to create a unique subscription id - **************************************************************************/ - -void -Grep::PSCoord::execGREP_CREATE_SUBID_REQ(Signal* signal) -{ - jamEntry(); - - CreateSubscriptionIdReq * req = - (CreateSubscriptionIdReq*)signal->getDataPtr(); - BlockReference ref = signal->getSendersBlockRef(); - - SubCoordinatorPtr subPtr; - if( !c_subCoordinatorPool.seize(subPtr)) { - jam(); - SubCoordinator sub; - sub.m_subscriberRef = ref; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sendRefToSS(signal, sub, GrepError::SUBSCRIPTION_ID_NOMEM ); - return; - } - prepareOperationRec(subPtr, - ref, - 0,0, - GSN_CREATE_SUBID_REQ); - - - ndbout_c("SUBID_REQ Ref %d",ref); - req->senderData=subPtr.p->m_subscriberData; - - sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal, - SubCreateReq::SignalLength, JBB); - -#if 1 //def DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSCoord: Sent CREATE_SUBID_REQ to SUMA"); -#endif -} - -void -Grep::PSCoord::execCREATE_SUBID_CONF(Signal* signal) -{ - jamEntry(); - CreateSubscriptionIdConf const * conf = - (CreateSubscriptionIdConf *)signal->getDataPtr(); - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 subData = conf->subscriberData; - -#if 1 //def DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSCoord: Recd GREP_SUBID_CONF (subId:%d, subKey:%d)", - subId, subKey); -#endif - - SubCoordinatorPtr subPtr; - c_subCoordinatorPool.getPtr(subPtr, subData); - BlockReference repRef = subPtr.p->m_subscriberRef; - - { // Check that id/key is unique - SubCoordinator key; - SubCoordinatorPtr tmp; - key.m_subscriptionId = subId; - key.m_subscriptionKey = subKey; - if(c_runningSubscriptions.find(tmp, key)){ - jam(); - SubCoordinator sub; - sub.m_subscriberRef=repRef; - sub.m_subscriptionId = subId; - sub.m_subscriptionKey = subKey; - sendRefToSS(signal,sub, GrepError::SUBSCRIPTION_ID_NOT_UNIQUE ); - return; - } - } - - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_CREATE_SUBID_CONF, signal, - CreateSubscriptionIdConf::SignalLength, JBB); - c_subCoordinatorPool.release(subData); - - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionInfo, - GrepEvent::GrepPS_CreateSubIdConf, - subId, - subKey, - (Uint32)GrepError::GE_NO_ERROR); -} - -void -Grep::PSCoord::execCREATE_SUBID_REF(Signal* signal) { - jamEntry(); - CreateSubscriptionIdRef const * ref = - (CreateSubscriptionIdRef *)signal->getDataPtr(); - Uint32 subData = ref->subscriberData; - GrepError::GE_Code err; - - Uint32 sendersBlockRef = signal->getSendersBlockRef(); - if(sendersBlockRef == SUMA_REF) - { - jam(); - err = GrepError::SUBSCRIPTION_ID_SUMA_FAILED_CREATE; - } else { - jam(); - ndbrequire(false); /* Added since errorcode err unhandled - * TODO: fix correct errorcode - */ - err= GrepError::GE_NO_ERROR; // remove compiler warning - } - - SubCoordinatorPtr subPtr; - c_runningSubscriptions.getPtr(subPtr, subData); - BlockReference repref = subPtr.p->m_subscriberRef; - - SubCoordinator sub; - sub.m_subscriberRef = repref; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sendRefToSS(signal,sub, err); - -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: CREATE SUBSCRIPTION - * ------------------------------------------------------------------------ - * - * Creates a subscription for every GREP to its local SUMA. - * GREP node that executes createSubscription becomes the GREP Coord. - **************************************************************************/ - -/** - * Request to create a subscription (sent from SS) - */ -void -Grep::PSCoord::execGREP_SUB_CREATE_REQ(Signal* signal) -{ - jamEntry(); - GrepSubCreateReq const * grepReq = (GrepSubCreateReq *)signal->getDataPtr(); - Uint32 subId = grepReq->subscriptionId; - Uint32 subKey = grepReq->subscriptionKey; - Uint32 subType = grepReq->subscriptionType; - BlockReference rep = signal->getSendersBlockRef(); - - GrepCreateReq * req =(GrepCreateReq*)grepReq; - - SubCoordinatorPtr subPtr; - - if( !c_subCoordinatorPool.seize(subPtr)) { - jam(); - SubCoordinator sub; - sub.m_subscriberRef = rep; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sub.m_outstandingRequest = GSN_GREP_CREATE_REQ; - sendRefToSS(signal, sub, GrepError::NOSPACE_IN_POOL); - return; - } - prepareOperationRec(subPtr, - numberToRef(PSREPBLOCKNO, refToNode(rep)), subId, subKey, - GSN_GREP_CREATE_REQ); - - /* Get the payload of the signal. - */ - SegmentedSectionPtr selectedTablesPtr; - if(subType == SubCreateReq::SelectiveTableSnapshot) { - jam(); - ndbrequire(signal->getNoOfSections()==1); - signal->getSection(selectedTablesPtr,0); - signal->header.m_noOfSections = 0; - } - /** - * Prepare the signal to be sent to Grep participatns - */ - subPtr.p->m_subscriptionType = subType; - req->senderRef = reference(); - req->subscriberRef = numberToRef(PSREPBLOCKNO, refToNode(rep)); - req->subscriberData = subPtr.p->m_subscriberData; - req->subscriptionId = subId; - req->subscriptionKey = subKey; - req->subscriptionType = subType; - - /*add payload if it is a selectivetablesnap*/ - if(subType == SubCreateReq::SelectiveTableSnapshot) { - jam(); - signal->setSection(selectedTablesPtr, 0); - } - - /****************************** - * Send to all PS participants - ******************************/ - NodeReceiverGroup rg(GREP, m_grep->m_aliveNodes); - subPtr.p->m_outstandingParticipants = rg; - sendSignal(rg, - GSN_GREP_CREATE_REQ, signal, - GrepCreateReq::SignalLength, JBB); - - -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSCoord: Sent GREP_CREATE_REQ " - "(subId:%d, subKey:%d, subData:%d, subType:%d) to parts", - subId, subKey, subPtr.p->m_subscriberData, subType); -#endif -} - -void -Grep::PSPart::execGREP_CREATE_REQ(Signal* signal) -{ - jamEntry(); - GrepCreateReq * const grepReq = (GrepCreateReq *)signal->getDataPtr(); - const Uint32 subId = grepReq->subscriptionId; - const Uint32 subKey = grepReq->subscriptionKey; - const Uint32 subData = grepReq->subscriberData; - const Uint32 subType = grepReq->subscriptionType; - const Uint32 coordinatorRef = grepReq->senderRef; - const Uint32 subRef = grepReq->subscriberRef; //this is ref to the - //REP node for this - //subscription. - - SubscriptionPtr subPtr; - ndbrequire( c_subscriptionPool.seize(subPtr)); - subPtr.p->m_coordinatorRef = coordinatorRef; - subPtr.p->m_subscriptionId = subId; - subPtr.p->m_subscriptionKey = subKey; - subPtr.p->m_subscriberRef = subRef; - subPtr.p->m_subscriberData = subPtr.i; - subPtr.p->m_subscriptionType = subType; - subPtr.p->m_outstandingRequest = GSN_GREP_CREATE_REQ; - subPtr.p->m_operationPtrI = subData; - - c_subscriptions.add(subPtr); - - SegmentedSectionPtr selectedTablesPtr; - if(subType == SubCreateReq::SelectiveTableSnapshot) { - jam(); - ndbrequire(signal->getNoOfSections()==1); - signal->getSection(selectedTablesPtr,0);// SubCreateReq::TABLE_LIST); - signal->header.m_noOfSections = 0; - } - - /** - * Prepare signal to be sent to SUMA - */ - SubCreateReq * sumaReq = (SubCreateReq *)grepReq; - sumaReq->subscriberRef = GREP_REF; - sumaReq->subscriberData = subPtr.p->m_subscriberData; - sumaReq->subscriptionId = subPtr.p->m_subscriptionId; - sumaReq->subscriptionKey = subPtr.p->m_subscriptionKey; - sumaReq->subscriptionType = subPtr.p->m_subscriptionType; - /*add payload if it is a selectivetablesnap*/ - if(subType == SubCreateReq::SelectiveTableSnapshot) { - jam(); - signal->setSection(selectedTablesPtr, 0); - } - sendSignal(SUMA_REF, - GSN_SUB_CREATE_REQ, - signal, - SubCreateReq::SignalLength, - JBB); -} - -void -Grep::PSPart::execSUB_CREATE_CONF(Signal* signal) -{ - jamEntry(); - - SubCreateConf * const conf = (SubCreateConf *)signal->getDataPtr(); - Uint32 subData = conf->subscriberData; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - /** - @todo check why this can fuck up -johan - - ndbrequire(subPtr.p->m_subscriptionId == conf->subscriptionId); - ndbrequire(subPtr.p->m_subscriptionKey == conf->subscriptionKey); - */ -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSPart: Recd SUB_CREATE_CONF " - "(subId:%d, subKey:%d) from SUMA", - conf->subscriptionId, conf->subscriptionKey); -#endif - - /********************* - * Send conf to coord - *********************/ - GrepCreateConf * grepConf = (GrepCreateConf*)conf; - grepConf->senderNodeId = getOwnNodeId(); - grepConf->senderData = subPtr.p->m_operationPtrI; - sendSignal(subPtr.p->m_coordinatorRef, GSN_GREP_CREATE_CONF, signal, - GrepCreateConf::SignalLength, JBB); - subPtr.p->m_outstandingRequest = 0; -} - -/** - * Handle errors that either occured in: - * 1) PSPart - * or - * 2) propagated from local SUMA - */ -void -Grep::PSPart::execSUB_CREATE_REF(Signal* signal) -{ - jamEntry(); - SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr(); - Uint32 subData = ref->subscriberData; - GrepError::GE_Code err = (GrepError::GE_Code)ref->err; - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - sendRefToPSCoord(signal, *subPtr.p, err /*error*/); - subPtr.p->m_outstandingRequest = 0; -} - -void -Grep::PSCoord::execGREP_CREATE_CONF(Signal* signal) -{ - jamEntry(); - GrepCreateConf const * conf = (GrepCreateConf *)signal->getDataPtr(); - Uint32 subData = conf->senderData; - Uint32 nodeId = conf->senderNodeId; - - SubCoordinatorPtr subPtr; - c_subCoordinatorPool.getPtr(subPtr, subData); - - ndbrequire(subPtr.p->m_outstandingRequest == GSN_GREP_CREATE_REQ); - - subPtr.p->m_outstandingParticipants.clearWaitingFor(nodeId); - - if(!subPtr.p->m_outstandingParticipants.done()) return; - /******************************** - * All participants have CONF:ed - ********************************/ - Uint32 subId = subPtr.p->m_subscriptionId; - Uint32 subKey = subPtr.p->m_subscriptionKey; - - GrepSubCreateConf * grepConf = (GrepSubCreateConf *)signal->getDataPtr(); - grepConf->subscriptionId = subId; - grepConf->subscriptionKey = subKey; - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_SUB_CREATE_CONF, signal, - GrepSubCreateConf::SignalLength, JBB); - - /** - * Send event report - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionInfo, - GrepEvent::GrepPS_SubCreateConf, - subId, - subKey, - (Uint32)GrepError::GE_NO_ERROR); - - c_subCoordinatorPool.release(subPtr); - -} - -/** - * Handle errors that either occured in: - * 1) PSCoord - * or - * 2) propagated from PSPart - */ -void -Grep::PSCoord::execGREP_CREATE_REF(Signal* signal) -{ - jamEntry(); - GrepCreateRef * const ref = (GrepCreateRef *)signal->getDataPtr(); - Uint32 subData = ref->senderData; - Uint32 err = ref->err; - SubCoordinatorPtr subPtr; - c_runningSubscriptions.getPtr(subPtr, subData); - - sendRefToSS(signal, *subPtr.p, (GrepError::GE_Code)err /*error*/); -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: START SUBSCRIPTION - * ------------------------------------------------------------------------ - * - * Starts a subscription at SUMA. - * Each participant starts its own subscription. - **************************************************************************/ - -/** - * Request to start subscription (Sent from SS) - */ -void -Grep::PSCoord::execGREP_SUB_START_REQ(Signal* signal) -{ - jamEntry(); - GrepSubStartReq * const subReq = (GrepSubStartReq *)signal->getDataPtr(); - SubscriptionData::Part part = (SubscriptionData::Part) subReq->part; - Uint32 subId = subReq->subscriptionId; - Uint32 subKey = subReq->subscriptionKey; - BlockReference rep = signal->getSendersBlockRef(); - - SubCoordinatorPtr subPtr; - - if(!c_subCoordinatorPool.seize(subPtr)) { - jam(); - SubCoordinator sub; - sub.m_subscriberRef = rep; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sub.m_outstandingRequest = GSN_GREP_START_REQ; - sendRefToSS(signal, sub, GrepError::NOSPACE_IN_POOL); - return; - } - - prepareOperationRec(subPtr, - numberToRef(PSREPBLOCKNO, refToNode(rep)), - subId, subKey, - GSN_GREP_START_REQ); - - GrepStartReq * const req = (GrepStartReq *) subReq; - req->part = (Uint32) part; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->senderData = subPtr.p->m_subscriberData; - - /*************************** - * Send to all participants - ***************************/ - NodeReceiverGroup rg(GREP, m_grep->m_aliveNodes); - subPtr.p->m_outstandingParticipants = rg; - sendSignal(rg, - GSN_GREP_START_REQ, - signal, - GrepStartReq::SignalLength, JBB); - -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSCoord: Sent GREP_START_REQ " - "(subId:%d, subKey:%d, senderData:%d, part:%d) to all participants", - req->subscriptionId, req->subscriptionKey, req->senderData, part); -#endif -} - - -void -Grep::PSPart::execGREP_START_REQ(Signal* signal) -{ - jamEntry(); - GrepStartReq * const grepReq = (GrepStartReq *) signal->getDataPtr(); - SubscriptionData::Part part = (SubscriptionData::Part)grepReq->part; - Uint32 subId = grepReq->subscriptionId; - Uint32 subKey = grepReq->subscriptionKey; - Uint32 operationPtrI = grepReq->senderData; - - Subscription key; - key.m_subscriptionId = subId; - key.m_subscriptionKey = subKey; - SubscriptionPtr subPtr; - ndbrequire(c_subscriptions.find(subPtr, key));; - subPtr.p->m_outstandingRequest = GSN_GREP_START_REQ; - subPtr.p->m_operationPtrI = operationPtrI; - /** - * send SUB_START_REQ to local SUMA - */ - SubStartReq * sumaReq = (SubStartReq *) grepReq; - sumaReq->subscriptionId = subId; - sumaReq->subscriptionKey = subKey; - sumaReq->subscriberData = subPtr.i; - sumaReq->part = (Uint32) part; - - sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, - SubStartReq::SignalLength, JBB); -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSPart: Sent SUB_START_REQ (subId:%d, subKey:%d, part:%d)", - subId, subKey, (Uint32)part); -#endif -} - - -void -Grep::PSPart::execSUB_START_CONF(Signal* signal) -{ - jamEntry(); - - SubStartConf * const conf = (SubStartConf *) signal->getDataPtr(); - SubscriptionData::Part part = (SubscriptionData::Part)conf->part; - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 subData = conf->subscriberData; - Uint32 firstGCI = conf->firstGCI; -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSPart: Recd SUB_START_CONF " - "(subId:%d, subKey:%d, subData:%d)", - subId, subKey, subData); -#endif - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - ndbrequire(subPtr.p->m_subscriptionId == subId); - ndbrequire(subPtr.p->m_subscriptionKey == subKey); - - GrepStartConf * grepConf = (GrepStartConf *)conf; - grepConf->senderData = subPtr.p->m_operationPtrI; - grepConf->part = (Uint32) part; - grepConf->subscriptionKey = subKey; - grepConf->subscriptionId = subId; - grepConf->firstGCI = firstGCI; - grepConf->senderNodeId = getOwnNodeId(); - sendSignal(subPtr.p->m_coordinatorRef, GSN_GREP_START_CONF, signal, - GrepStartConf::SignalLength, JBB); - subPtr.p->m_outstandingRequest = 0; - -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSPart: Sent GREP_START_CONF " - "(subId:%d, subKey:%d, subData:%d, part:%d)", - subId, subKey, subData, part); -#endif -} - - -/** - * Handle errors that either occured in: - * 1) PSPart - * or - * 2) propagated from local SUMA - * - * Propagates REF signal to PSCoord - */ -void -Grep::PSPart::execSUB_START_REF(Signal* signal) -{ - SubStartRef * const ref = (SubStartRef *)signal->getDataPtr(); - Uint32 subData = ref->subscriberData; - GrepError::GE_Code err = (GrepError::GE_Code)ref->err; - SubscriptionData::Part part = (SubscriptionData::Part)ref->part; - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - sendRefToPSCoord(signal, *subPtr.p, err /*error*/, part); - subPtr.p->m_outstandingRequest = 0; -} - - -/** - * Logging has started... (says PS Participant) - */ -void -Grep::PSCoord::execGREP_START_CONF(Signal* signal) -{ - jamEntry(); - - GrepStartConf * const conf = (GrepStartConf *) signal->getDataPtr(); - Uint32 subData = conf->senderData; - SubscriptionData::Part part = (SubscriptionData::Part)conf->part; - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 firstGCI = conf->firstGCI; - - SubCoordinatorPtr subPtr; - c_subCoordinatorPool.getPtr(subPtr, subData); - ndbrequire(subPtr.p->m_outstandingRequest == GSN_GREP_START_REQ); - - subPtr.p->m_outstandingParticipants.clearWaitingFor(conf->senderNodeId); - - if(!subPtr.p->m_outstandingParticipants.done()) return; - jam(); - - /************************* - * All participants ready - *************************/ - GrepSubStartConf * grepConf = (GrepSubStartConf *) conf; - grepConf->part = part; - grepConf->subscriptionId = subId; - grepConf->subscriptionKey = subKey; - grepConf->firstGCI = firstGCI; - - bool ok = false; - switch(part) { - case SubscriptionData::MetaData: - ok = true; - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_SUB_START_CONF, signal, - GrepSubStartConf::SignalLength, JBB); - - /** - * Send event report - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionInfo, - GrepEvent::GrepPS_SubStartMetaConf, - subId, subKey, - (Uint32)GrepError::GE_NO_ERROR); - - c_subCoordinatorPool.release(subPtr); - break; - case SubscriptionData::TableData: - ok = true; - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_SUB_START_CONF, signal, - GrepSubStartConf::SignalLength, JBB); - - /** - * Send event report - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionInfo, - GrepEvent::GrepPS_SubStartDataConf, - subId, subKey, - (Uint32)GrepError::GE_NO_ERROR); - - - c_subCoordinatorPool.release(subPtr); - break; - } - ndbrequire(ok); - -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSCoord: Recd SUB_START_CONF (subId:%d, subKey:%d, part:%d) " - "from all slaves", - subId, subKey, (Uint32)part); -#endif -} - -/** - * Handle errors that either occured in: - * 1) PSCoord - * or - * 2) propagated from PSPart - */ -void -Grep::PSCoord::execGREP_START_REF(Signal* signal) -{ - jamEntry(); - GrepStartRef * const ref = (GrepStartRef *)signal->getDataPtr(); - Uint32 subData = ref->senderData; - GrepError::GE_Code err = (GrepError::GE_Code)ref->err; - SubscriptionData::Part part = (SubscriptionData::Part)ref->part; - - SubCoordinatorPtr subPtr; - c_runningSubscriptions.getPtr(subPtr, subData); - sendRefToSS(signal, *subPtr.p, err /*error*/, part); -} - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: REMOVE SUBSCRIPTION - * ------------------------------------------------------------------------ - * - * Remove a subscription at SUMA. - * Each participant removes its own subscription. - * We start by deleting the subscription inside the requestor - * since, we don't know if nodes (REP nodes or DB nodes) - * have disconnected after we sent out this and - * if we dont delete the sub in the requestor now, - * we won't be able to create a new subscription - **************************************************************************/ - -/** - * Request to abort subscription (Sent from SS) - */ -void -Grep::PSCoord::execGREP_SUB_REMOVE_REQ(Signal* signal) -{ - jamEntry(); - GrepSubRemoveReq * const subReq = (GrepSubRemoveReq *)signal->getDataPtr(); - Uint32 subId = subReq->subscriptionId; - Uint32 subKey = subReq->subscriptionKey; - BlockReference rep = signal->getSendersBlockRef(); - - SubCoordinatorPtr subPtr; - if( !c_subCoordinatorPool.seize(subPtr)) { - jam(); - SubCoordinator sub; - sub.m_subscriberRef = rep; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sub.m_outstandingRequest = GSN_GREP_REMOVE_REQ; - sendRefToSS(signal, sub, GrepError::NOSPACE_IN_POOL); - return; - } - - - prepareOperationRec(subPtr, - numberToRef(PSREPBLOCKNO, refToNode(rep)), - subId, subKey, - GSN_GREP_REMOVE_REQ); - - c_runningSubscriptions.add(subPtr); - - GrepRemoveReq * req = (GrepRemoveReq *) subReq; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->senderData = subPtr.p->m_subscriberData; - req->senderRef = subPtr.p->m_coordinatorRef; - - /*************************** - * Send to all participants - ***************************/ - NodeReceiverGroup rg(GREP, m_grep->m_aliveNodes); - subPtr.p->m_outstandingParticipants = rg; - sendSignal(rg, - GSN_GREP_REMOVE_REQ, signal, - GrepRemoveReq::SignalLength, JBB); -} - - -void -Grep::PSPart::execGREP_REMOVE_REQ(Signal* signal) -{ - jamEntry(); - GrepRemoveReq * const grepReq = (GrepRemoveReq *) signal->getDataPtr(); - Uint32 subId = grepReq->subscriptionId; - Uint32 subKey = grepReq->subscriptionKey; - Uint32 subData = grepReq->senderData; - Uint32 coordinator = grepReq->senderRef; - - Subscription key; - key.m_subscriptionId = subId; - key.m_subscriptionKey = subKey; - SubscriptionPtr subPtr; - - if(!c_subscriptions.find(subPtr, key)) - { - /** - * The subscription was not found, so it must be deleted. - * Send CONF back, since it does not exist (thus, it is removed) - */ - GrepRemoveConf * grepConf = (GrepRemoveConf *)grepReq; - grepConf->subscriptionKey = subKey; - grepConf->subscriptionId = subId; - grepConf->senderData = subData; - grepConf->senderNodeId = getOwnNodeId(); - sendSignal(coordinator, GSN_GREP_REMOVE_CONF, signal, - GrepRemoveConf::SignalLength, JBB); - return; - } - - subPtr.p->m_operationPtrI = subData; - subPtr.p->m_coordinatorRef = coordinator; - subPtr.p->m_outstandingRequest = GSN_GREP_REMOVE_REQ; - - /** - * send SUB_REMOVE_REQ to local SUMA - */ - SubRemoveReq * sumaReq = (SubRemoveReq *) grepReq; - sumaReq->subscriptionId = subId; - sumaReq->subscriptionKey = subKey; - sumaReq->senderData = subPtr.i; - sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, - SubStartReq::SignalLength, JBB); -} - - -/** - * SUB_REMOVE_CONF (from local SUMA) - */ -void -Grep::PSPart::execSUB_REMOVE_CONF(Signal* signal) -{ - jamEntry(); - SubRemoveConf * const conf = (SubRemoveConf *) signal->getDataPtr(); - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 subData = conf->subscriberData; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - ndbrequire(subPtr.p->m_subscriptionId == subId); - ndbrequire(subPtr.p->m_subscriptionKey == subKey); - subPtr.p->m_outstandingRequest = 0; - GrepRemoveConf * grepConf = (GrepRemoveConf *)conf; - grepConf->subscriptionKey = subKey; - grepConf->subscriptionId = subId; - grepConf->senderData = subPtr.p->m_operationPtrI; - grepConf->senderNodeId = getOwnNodeId(); - sendSignal(subPtr.p->m_coordinatorRef, GSN_GREP_REMOVE_CONF, signal, - GrepRemoveConf::SignalLength, JBB); - c_subscriptions.release(subPtr); - -} - - -/** - * SUB_REMOVE_CONF (from local SUMA) - */ -void -Grep::PSPart::execSUB_REMOVE_REF(Signal* signal) -{ - jamEntry(); - SubRemoveRef * const ref = (SubRemoveRef *)signal->getDataPtr(); - Uint32 subData = ref->subscriberData; - /* GrepError::GE_Code err = (GrepError::GE_Code)ref->err;*/ - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - - //sendSubRemoveRef_PSCoord(signal, *subPtr.p, err /*error*/); -} - - -/** - * Aborting has been carried out (says Participants) - */ -void -Grep::PSCoord::execGREP_REMOVE_CONF(Signal* signal) -{ - jamEntry(); - GrepRemoveConf * const conf = (GrepRemoveConf *) signal->getDataPtr(); - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 senderNodeId = conf->senderNodeId; - Uint32 subData = conf->senderData; - SubCoordinatorPtr subPtr; - c_subCoordinatorPool.getPtr(subPtr, subData); - - ndbrequire(subPtr.p->m_outstandingRequest == GSN_GREP_REMOVE_REQ); - - subPtr.p->m_outstandingParticipants.clearWaitingFor(senderNodeId); - - if(!subPtr.p->m_outstandingParticipants.done()) { - jam(); - return; - } - jam(); - - /************************* - * All participants ready - *************************/ - - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionInfo, - GrepEvent::GrepPS_SubRemoveConf, - subId, subKey, - GrepError::GE_NO_ERROR); - - GrepSubRemoveConf * grepConf = (GrepSubRemoveConf *) conf; - grepConf->subscriptionId = subId; - grepConf->subscriptionKey = subKey; - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_SUB_REMOVE_CONF, signal, - GrepSubRemoveConf::SignalLength, JBB); - - c_subCoordinatorPool.release(subPtr); -} - - - -void -Grep::PSCoord::execGREP_REMOVE_REF(Signal* signal) -{ - jamEntry(); - GrepRemoveRef * const ref = (GrepRemoveRef *)signal->getDataPtr(); - Uint32 subData = ref->senderData; - Uint32 err = ref->err; - SubCoordinatorPtr subPtr; - - /** - * Get the operationrecord matching subdata and remove it. Subsequent - * execGREP_REMOVE_REF will simply be ignored at this stage. - */ - for( c_runningSubscriptions.first(c_subPtr); - !c_subPtr.isNull(); c_runningSubscriptions.next(c_subPtr)) { - jam(); - subPtr.i = c_subPtr.curr.i; - subPtr.p = c_runningSubscriptions.getPtr(subPtr.i); - if(subData == subPtr.i) - { - sendRefToSS(signal, *subPtr.p, (GrepError::GE_Code)err /*error*/); - c_runningSubscriptions.release(subPtr); - return; - } - } - return; -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: LOG RECORDS (COMING IN FROM LOCAL SUMA) - * ------------------------------------------------------------------------ - * - * After the subscription is started, we get log records from SUMA. - * Both table data and meta data log records are received. - * - * TODO: - * @todo Changes in meta data is currently not - * allowed during global replication - **************************************************************************/ - -void -Grep::PSPart::execSUB_META_DATA(Signal* signal) -{ - jamEntry(); - if(m_recoveryMode) { - jam(); - return; - } - /** - * METASCAN and METALOG - */ - SubMetaData * data = (SubMetaData *) signal->getDataPtrSend(); - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, data->subscriberData); - - /*************************** - * Forward data to REP node - ***************************/ - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_META_DATA, signal, - SubMetaData::SignalLength, JBB); -#ifdef DEBUG_GREP_SUBSCRIPTION - ndbout_c("Grep::PSPart: Sent SUB_META_DATA to REP " - "(TableId: %d, SenderData: %d, GCI: %d)", - data->tableId, data->senderData, data->gci); -#endif -} - -/** - * Receive table data from SUMA and dispatches it to REP node. - */ -void -Grep::PSPart::execSUB_TABLE_DATA(Signal* signal) -{ - jamEntry(); - if(m_recoveryMode) { - jam(); - return; - } - ndbrequire(m_repRef!=0); - - if(!assembleFragments(signal)) { jam(); return; } - - /** - * Check if it is SCAN or LOG data that has arrived - */ - if(signal->getNoOfSections() == 2) - { - jam(); - /** - * DATASCAN - Not marked with GCI, so mark with latest seen GCI - */ - if(m_firstScanGCI == 1 && m_lastScanGCI == 0) { - m_firstScanGCI = m_latestSeenGCI; - m_lastScanGCI = m_latestSeenGCI; - } - SubTableData * data = (SubTableData*)signal->getDataPtrSend(); - Uint32 subData = data->senderData; - data->gci = m_latestSeenGCI; - data->logType = SubTableData::SCAN; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_TABLE_DATA, signal, - SubTableData::SignalLength, JBB); -#ifdef DEBUG_GREP - ndbout_c("Grep::PSPart: Sent SUB_TABLE_DATA (Scan, GCI: %d)", - data->gci); -#endif - } - else - { - jam(); - /** - * DATALOG (TRIGGER) - Already marked with GCI - */ - SubTableData * data = (SubTableData*)signal->getDataPtrSend(); - data->logType = SubTableData::LOG; - Uint32 subData = data->senderData; - if (data->gci > m_latestSeenGCI) m_latestSeenGCI = data->gci; - - // Reformat to sections and send to replication node. - LinearSectionPtr ptr[3]; - ptr[0].p = signal->theData + 25; - ptr[0].sz = data->noOfAttributes; - ptr[1].p = signal->theData + 25 + MAX_ATTRIBUTES_IN_TABLE; - ptr[1].sz = data->dataSize; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_TABLE_DATA, - signal, SubTableData::SignalLength, JBB, ptr, 2); -#ifdef DEBUG_GREP - ndbout_c("Grep::PSPart: Sent SUB_TABLE_DATA (Log, GCI: %d)", - data->gci); -#endif - } -} - - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: START SYNCHRONIZATION - * ------------------------------------------------------------------------ - * - * - **************************************************************************/ - -/** - * Request to start sync (from Rep SS) - */ -void -Grep::PSCoord::execGREP_SUB_SYNC_REQ(Signal* signal) -{ - jamEntry(); - GrepSubSyncReq * const subReq = (GrepSubSyncReq*)signal->getDataPtr(); - SubscriptionData::Part part = (SubscriptionData::Part) subReq->part; - Uint32 subId = subReq->subscriptionId; - Uint32 subKey = subReq->subscriptionKey; - BlockReference rep = signal->getSendersBlockRef(); - - SubCoordinatorPtr subPtr; - if( !c_subCoordinatorPool.seize(subPtr)) { - jam(); - SubCoordinator sub; - sub.m_subscriberRef = rep; - sub.m_subscriptionId = 0; - sub.m_subscriptionKey = 0; - sub.m_outstandingRequest = GSN_GREP_SYNC_REQ; - sendRefToSS(signal, sub, GrepError::NOSPACE_IN_POOL); - return; - } - - prepareOperationRec(subPtr, - numberToRef(PSREPBLOCKNO, refToNode(rep)), - subId, subKey, - GSN_GREP_SYNC_REQ); - - GrepSyncReq * req = (GrepSyncReq *)subReq; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->senderData = subPtr.p->m_subscriberData; - req->part = (Uint32)part; - - /*************************** - * Send to all participants - ***************************/ - NodeReceiverGroup rg(GREP, m_grep->m_aliveNodes); - subPtr.p->m_outstandingParticipants = rg; - sendSignal(rg, - GSN_GREP_SYNC_REQ, signal, GrepSyncReq::SignalLength, JBB); -} - - -/** - * Sync req from Grep::PSCoord to PS particpant - */ -void -Grep::PSPart::execGREP_SYNC_REQ(Signal* signal) -{ - jamEntry(); - - GrepSyncReq * const grepReq = (GrepSyncReq *) signal->getDataPtr(); - Uint32 part = grepReq->part; - Uint32 subId = grepReq->subscriptionId; - Uint32 subKey = grepReq->subscriptionKey; - Uint32 subData = grepReq->senderData; - - Subscription key; - key.m_subscriptionId = subId; - key.m_subscriptionKey = subKey; - SubscriptionPtr subPtr; - ndbrequire(c_subscriptions.find(subPtr, key)); - subPtr.p->m_operationPtrI = subData; - subPtr.p->m_outstandingRequest = GSN_GREP_SYNC_REQ; - /********************************** - * Send SUB_SYNC_REQ to local SUMA - **********************************/ - SubSyncReq * sumaReq = (SubSyncReq *)grepReq; - sumaReq->subscriptionId = subId; - sumaReq->subscriptionKey = subKey; - sumaReq->subscriberData = subPtr.i; - sumaReq->part = part; - sendSignal(SUMA_REF, GSN_SUB_SYNC_REQ, signal, - SubSyncReq::SignalLength, JBB); -} - - -/** - * SYNC conf from SUMA - */ -void -Grep::PSPart::execSUB_SYNC_CONF(Signal* signal) -{ - jamEntry(); - - SubSyncConf * const conf = (SubSyncConf *) signal->getDataPtr(); - Uint32 part = conf->part; - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 subData = conf->subscriberData; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - - ndbrequire(subPtr.p->m_subscriptionId == subId); - ndbrequire(subPtr.p->m_subscriptionKey == subKey); - - GrepSyncConf * grepConf = (GrepSyncConf *)conf; - grepConf->senderNodeId = getOwnNodeId(); - grepConf->part = part; - grepConf->firstGCI = m_firstScanGCI; - grepConf->lastGCI = m_lastScanGCI; - grepConf->subscriptionId = subId; - grepConf->subscriptionKey = subKey; - grepConf->senderData = subPtr.p->m_operationPtrI; - sendSignal(subPtr.p->m_coordinatorRef, GSN_GREP_SYNC_CONF, signal, - GrepSyncConf::SignalLength, JBB); - - m_firstScanGCI = 1; - m_lastScanGCI = 0; - subPtr.p->m_outstandingRequest = 0; -} - -/** - * Handle errors that either occured in: - * 1) PSPart - * or - * 2) propagated from local SUMA - * - * Propagates REF signal to PSCoord - */ -void -Grep::PSPart::execSUB_SYNC_REF(Signal* signal) { - jamEntry(); - SubSyncRef * const ref = (SubSyncRef *)signal->getDataPtr(); - Uint32 subData = ref->subscriberData; - GrepError::GE_Code err = (GrepError::GE_Code)ref->err; - SubscriptionData::Part part = (SubscriptionData::Part)ref->part; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subData); - sendRefToPSCoord(signal, *subPtr.p, err /*error*/ ,part); - subPtr.p->m_outstandingRequest = 0; -} - -/** - * Syncing has started... (says PS Participant) - */ -void -Grep::PSCoord::execGREP_SYNC_CONF(Signal* signal) -{ - jamEntry(); - - GrepSyncConf const * conf = (GrepSyncConf *)signal->getDataPtr(); - Uint32 part = conf->part; - Uint32 firstGCI = conf->firstGCI; - Uint32 lastGCI = conf->lastGCI; - Uint32 subId = conf->subscriptionId; - Uint32 subKey = conf->subscriptionKey; - Uint32 subData = conf->senderData; - - SubCoordinatorPtr subPtr; - c_subCoordinatorPool.getPtr(subPtr, subData); - ndbrequire(subPtr.p->m_outstandingRequest == GSN_GREP_SYNC_REQ); - - subPtr.p->m_outstandingParticipants.clearWaitingFor(conf->senderNodeId); - if(!subPtr.p->m_outstandingParticipants.done()) return; - - /** - * Send event - */ - GrepEvent::Subscription event; - if(part == SubscriptionData::MetaData) - event = GrepEvent::GrepPS_SubSyncMetaConf; - else - event = GrepEvent::GrepPS_SubSyncDataConf; - - /* @todo Johan: Add firstGCI here. /Lars */ - m_grep->sendEventRep(signal, EventReport::GrepSubscriptionInfo, - event, subId, subKey, - (Uint32)GrepError::GE_NO_ERROR, - lastGCI); - - /************************* - * All participants ready - *************************/ - GrepSubSyncConf * grepConf = (GrepSubSyncConf *)conf; - grepConf->part = part; - grepConf->firstGCI = firstGCI; - grepConf->lastGCI = lastGCI; - grepConf->subscriptionId = subId; - grepConf->subscriptionKey = subKey; - - sendSignal(subPtr.p->m_subscriberRef, GSN_GREP_SUB_SYNC_CONF, signal, - GrepSubSyncConf::SignalLength, JBB); - c_subCoordinatorPool.release(subPtr); -} - -/** - * Handle errors that either occured in: - * 1) PSCoord - * or - * 2) propagated from PSPart - */ -void -Grep::PSCoord::execGREP_SYNC_REF(Signal* signal) { - jamEntry(); - GrepSyncRef * const ref = (GrepSyncRef *)signal->getDataPtr(); - Uint32 subData = ref->senderData; - SubscriptionData::Part part = (SubscriptionData::Part)ref->part; - GrepError::GE_Code err = (GrepError::GE_Code)ref->err; - SubCoordinatorPtr subPtr; - c_runningSubscriptions.getPtr(subPtr, subData); - sendRefToSS(signal, *subPtr.p, err /*error*/, part); -} - - - -void -Grep::PSCoord::sendRefToSS(Signal * signal, - SubCoordinator sub, - GrepError::GE_Code err, - SubscriptionData::Part part) { - /** - - GrepCreateRef * ref = (GrepCreateRef*)signal->getDataPtrSend(); - ref->senderData = sub.m_subscriberData; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->err = err; - sendSignal(sub.m_coordinatorRef, GSN_GREP_CREATE_REF, signal, - GrepCreateRef::SignalLength, JBB); -*/ - - jam(); - GrepEvent::Subscription event; - switch(sub.m_outstandingRequest) { - case GSN_GREP_CREATE_SUBID_REQ: - { - jam(); - CreateSubscriptionIdRef * ref = - (CreateSubscriptionIdRef*)signal->getDataPtrSend(); - ref->err = (Uint32)err; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - sendSignal(sub.m_subscriberRef, - GSN_GREP_CREATE_SUBID_REF, - signal, - CreateSubscriptionIdRef::SignalLength, - JBB); - event = GrepEvent::GrepPS_CreateSubIdRef; - } - break; - case GSN_GREP_CREATE_REQ: - { - jam(); - GrepSubCreateRef * ref = (GrepSubCreateRef*)signal->getDataPtrSend(); - ref->err = (Uint32)err; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - sendSignal(sub.m_subscriberRef, GSN_GREP_SUB_CREATE_REF, signal, - GrepSubCreateRef::SignalLength, JBB); - event = GrepEvent::GrepPS_SubCreateRef; - } - break; - case GSN_GREP_SYNC_REQ: - { - jam(); - GrepSubSyncRef * ref = (GrepSubSyncRef*)signal->getDataPtrSend(); - ref->err = (Uint32)err; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->part = (SubscriptionData::Part) part; - sendSignal(sub.m_subscriberRef, - GSN_GREP_SUB_SYNC_REF, - signal, - GrepSubSyncRef::SignalLength, - JBB); - if(part == SubscriptionData::MetaData) - event = GrepEvent::GrepPS_SubSyncMetaRef; - else - event = GrepEvent::GrepPS_SubSyncDataRef; - } - break; - case GSN_GREP_START_REQ: - { - jam(); - GrepSubStartRef * ref = (GrepSubStartRef*)signal->getDataPtrSend(); - ref->err = (Uint32)err; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - - sendSignal(sub.m_subscriberRef, GSN_GREP_SUB_START_REF, - signal, GrepSubStartRef::SignalLength, JBB); - if(part == SubscriptionData::MetaData) - event = GrepEvent::GrepPS_SubStartMetaRef; - else - event = GrepEvent::GrepPS_SubStartDataRef; - /** - * Send event report - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionAlert, - event, - sub.m_subscriptionId, - sub.m_subscriptionKey, - (Uint32)err); - } - break; - case GSN_GREP_REMOVE_REQ: - { - jam(); - GrepSubRemoveRef * ref = (GrepSubRemoveRef*)signal->getDataPtrSend(); - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->err = (Uint32)err; - - sendSignal(sub.m_subscriberRef, - GSN_GREP_SUB_REMOVE_REF, - signal, - GrepSubRemoveRef::SignalLength, - JBB); - - event = GrepEvent::GrepPS_SubRemoveRef; - } - break; - default: - ndbrequire(false); - event= GrepEvent::Rep_Disconnect; // remove compiler warning - } - /** - * Finally, send an event. - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionAlert, - event, - sub.m_subscriptionId, - sub.m_subscriptionKey, - err); - -} - - -void -Grep::PSPart::sendRefToPSCoord(Signal * signal, - Subscription sub, - GrepError::GE_Code err, - SubscriptionData::Part part) { - - jam(); - GrepEvent::Subscription event; - switch(sub.m_outstandingRequest) { - - case GSN_GREP_CREATE_REQ: - { - GrepCreateRef * ref = (GrepCreateRef*)signal->getDataPtrSend(); - ref->senderData = sub.m_subscriberData; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->err = err; - sendSignal(sub.m_coordinatorRef, GSN_GREP_CREATE_REF, signal, - GrepCreateRef::SignalLength, JBB); - - event = GrepEvent::GrepPS_SubCreateRef; - } - break; - case GSN_GREP_SYNC_REQ: - { - GrepSyncRef * ref = (GrepSyncRef*)signal->getDataPtrSend(); - ref->senderData = sub.m_subscriberData; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->part = part; - ref->err = err; - sendSignal(sub.m_coordinatorRef, - GSN_GREP_SYNC_REF, signal, - GrepSyncRef::SignalLength, JBB); - if(part == SubscriptionData::MetaData) - event = GrepEvent::GrepPS_SubSyncMetaRef; - else - event = GrepEvent::GrepPS_SubSyncDataRef; - } - break; - case GSN_GREP_START_REQ: - { - jam(); - GrepStartRef * ref = (GrepStartRef*)signal->getDataPtrSend(); - ref->senderData = sub.m_subscriberData; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->part = (Uint32) part; - ref->err = err; - sendSignal(sub.m_coordinatorRef, GSN_GREP_START_REF, signal, - GrepStartRef::SignalLength, JBB); - if(part == SubscriptionData::MetaData) - event = GrepEvent::GrepPS_SubStartMetaRef; - else - event = GrepEvent::GrepPS_SubStartDataRef; - } - break; - - case GSN_GREP_REMOVE_REQ: - { - jamEntry(); - GrepRemoveRef * ref = (GrepRemoveRef*)signal->getDataPtrSend(); - ref->senderData = sub.m_operationPtrI; - ref->subscriptionId = sub.m_subscriptionId; - ref->subscriptionKey = sub.m_subscriptionKey; - ref->err = err; - sendSignal(sub.m_coordinatorRef, GSN_GREP_REMOVE_REF, signal, - GrepCreateRef::SignalLength, JBB); - - } - break; - default: - ndbrequire(false); - event= GrepEvent::Rep_Disconnect; // remove compiler warning - } - - /** - * Finally, send an event. - */ - m_grep->sendEventRep(signal, - EventReport::GrepSubscriptionAlert, - event, - sub.m_subscriptionId, - sub.m_subscriptionKey, - err); - -} - -/************************************************************************** - * ------------------------------------------------------------------------ - * MODULE: GREP PS Coordinator GCP - * ------------------------------------------------------------------------ - * - * - **************************************************************************/ - -void -Grep::PSPart::execSUB_GCP_COMPLETE_REP(Signal* signal) -{ - jamEntry(); - if(m_recoveryMode) { - jam(); - return; - } - SubGcpCompleteRep * rep = (SubGcpCompleteRep *)signal->getDataPtrSend(); - rep->senderRef = reference(); - - if (rep->gci > m_latestSeenGCI) m_latestSeenGCI = rep->gci; - SubscriptionPtr subPtr; - c_subscriptions.first(c_subPtr); - for(; !c_subPtr.isNull(); c_subscriptions.next(c_subPtr)) { - - subPtr.i = c_subPtr.curr.i; - subPtr.p = c_subscriptions.getPtr(subPtr.i); - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_GCP_COMPLETE_REP, signal, - SubGcpCompleteRep::SignalLength, JBB); - } - -#ifdef DEBUG_GREP - ndbout_c("Grep::PSPart: Recd SUB_GCP_COMPLETE_REP " - "(GCI: %d, nodeId: %d) from SUMA", - rep->gci, refToNode(rep->senderRef)); -#endif -} - - -void -Grep::PSPart::execSUB_SYNC_CONTINUE_REQ(Signal* signal) -{ - jamEntry(); - SubSyncContinueReq * const req = (SubSyncContinueReq*)signal->getDataPtr(); - Uint32 subData = req->subscriberData; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr,subData); - - /** - * @todo Figure out how to control how much data we can receive? - */ - SubSyncContinueConf * conf = (SubSyncContinueConf*)req; - conf->subscriptionId = subPtr.p->m_subscriptionId; - conf->subscriptionKey = subPtr.p->m_subscriptionKey; - sendSignal(SUMA_REF, GSN_SUB_SYNC_CONTINUE_CONF, signal, - SubSyncContinueConf::SignalLength, JBB); -} - -void -Grep::sendEventRep(Signal * signal, - EventReport::EventType type, - GrepEvent::Subscription event, - Uint32 subId, - Uint32 subKey, - Uint32 err, - Uint32 other) { - jam(); - signal->theData[0] = type; - signal->theData[1] = event; - signal->theData[2] = subId; - signal->theData[3] = subKey; - signal->theData[4] = err; - - if(other==0) - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 5 ,JBB); - else { - signal->theData[5] = other; - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6 ,JBB); - } -} diff --git a/ndb/src/kernel/blocks/grep/Grep.hpp b/ndb/src/kernel/blocks/grep/Grep.hpp deleted file mode 100644 index 7d3dd916ecc..00000000000 --- a/ndb/src/kernel/blocks/grep/Grep.hpp +++ /dev/null @@ -1,535 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifndef GREP_HPP -#define GREP_HPP - -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include - - -/** - * Module in block (Should be placed elsewhere) - */ -class BlockComponent { -public: - BlockComponent(SimulatedBlock *); - BlockReference reference() { return m_sb->reference(); }; - BlockNumber number() { return m_sb->number(); }; - - void sendSignal(NodeReceiverGroup rg, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 length, - JobBufferLevel jbuf ) const { - m_sb->sendSignal(rg, gsn, signal, length, jbuf); - } - - void sendSignal(BlockReference ref, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 length, - JobBufferLevel jbuf ) const { - m_sb->sendSignal(ref, gsn, signal, length, jbuf); - } - - void sendSignal(BlockReference ref, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 length, - JobBufferLevel jbuf, - LinearSectionPtr ptr[3], - Uint32 noOfSections) const { - m_sb->sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections); - } - - void sendSignalWithDelay(BlockReference ref, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 delayInMilliSeconds, - Uint32 length) const { - - m_sb->sendSignalWithDelay(ref, gsn, signal, delayInMilliSeconds, length); - } - - NodeId getOwnNodeId() const { - return m_sb->getOwnNodeId(); - } - - bool assembleFragments(Signal * signal) { - return m_sb->assembleFragments(signal); - } - - void progError(int line, int err_code, const char* extra) { - m_sb->progError(line, err_code, extra); - } - -private: - SimulatedBlock * m_sb; -}; - - - -/** - * Participant of GREP Protocols (not necessarily a protocol coordinator) - * - * This object is only used on primary system - */ -#if 0 -class GrepParticipant : public SimulatedBlock -{ -protected: - GrepParticipant(const Configuration & conf); - virtual ~GrepParticipant(); - BLOCK_DEFINES(GrepParticipant); - -protected: - /*************************************************************************** - * SUMA Signal Interface - ***************************************************************************/ - void execSUB_CREATE_CONF(Signal*); - void execSUB_STARTCONF(Signal*); - void execSUB_REMOVE_CONF(Signal*); - - void execSUB_META_DATA(Signal*); - void execSUB_TABLE_DATA(Signal*); - - void execSUB_SYNC_CONF(Signal*); - - void execSUB_GCP_COMPLETE_REP(Signal*); - void execSUB_SYNC_CONTINUE_REQ(Signal*); - - /*************************************************************************** - * GREP Coordinator Signal Interface - ***************************************************************************/ - void execGREP_CREATE_REQ(Signal*); - void execGREP_START_REQ(Signal*); - void execGREP_SYNC_REQ(Signal*); - void execGREP_REMOVE_REQ(Signal*); - - -protected: - BlockReference m_repRef; ///< Replication node (only one rep node per grep) - -private: - BlockReference m_coordinator; - Uint32 m_latestSeenGCI; -}; -#endif - - -/** - * GREP Coordinator - */ -class Grep : public SimulatedBlock //GrepParticipant -{ - BLOCK_DEFINES(Grep); - -public: - Grep(const Configuration & conf); - virtual ~Grep(); - -private: - /*************************************************************************** - * General Signal Recivers - ***************************************************************************/ - void execSTTOR(Signal*); - void sendSTTORRY(Signal*); - void execNDB_STTOR(Signal*); - void execDUMP_STATE_ORD(Signal*); - void execREAD_NODESCONF(Signal*); - void execNODE_FAILREP(Signal*); - void execINCL_NODEREQ(Signal*); - void execGREP_REQ(Signal*); - void execAPI_FAILREQ(Signal*); - /** - * Forwarded to PSCoord - */ - //CONF - void fwdGREP_CREATE_CONF(Signal* s) { - pscoord.execGREP_CREATE_CONF(s); }; - void fwdGREP_START_CONF(Signal* s) { - pscoord.execGREP_START_CONF(s); }; - void fwdGREP_SYNC_CONF(Signal* s) { - pscoord.execGREP_SYNC_CONF(s); }; - void fwdGREP_REMOVE_CONF(Signal* s) { - pscoord.execGREP_REMOVE_CONF(s); }; - void fwdCREATE_SUBID_CONF(Signal* s) { - pscoord.execCREATE_SUBID_CONF(s); }; - - //REF - - void fwdGREP_CREATE_REF(Signal* s) { - pscoord.execGREP_CREATE_REF(s); }; - void fwdGREP_START_REF(Signal* s) { - pscoord.execGREP_START_REF(s); }; - void fwdGREP_SYNC_REF(Signal* s) { - pscoord.execGREP_SYNC_REF(s); }; - - void fwdGREP_REMOVE_REF(Signal* s) { - pscoord.execGREP_REMOVE_REF(s); }; - - void fwdCREATE_SUBID_REF(Signal* s) { - pscoord.execCREATE_SUBID_REF(s); }; - - //REQ - void fwdGREP_SUB_CREATE_REQ(Signal* s) { - pscoord.execGREP_SUB_CREATE_REQ(s); }; - void fwdGREP_SUB_START_REQ(Signal* s) { - pscoord.execGREP_SUB_START_REQ(s); }; - void fwdGREP_SUB_SYNC_REQ(Signal* s) { - pscoord.execGREP_SUB_SYNC_REQ(s); }; - void fwdGREP_SUB_REMOVE_REQ(Signal* s) { - pscoord.execGREP_SUB_REMOVE_REQ(s); }; - void fwdGREP_CREATE_SUBID_REQ(Signal* s) { - pscoord.execGREP_CREATE_SUBID_REQ(s); }; - - /** - * Forwarded to PSPart - */ - - void fwdSTART_ME(Signal* s){ - pspart.execSTART_ME(s); - }; - void fwdGREP_ADD_SUB_REQ(Signal* s){ - pspart.execGREP_ADD_SUB_REQ(s); - }; - void fwdGREP_ADD_SUB_REF(Signal* s){ - pspart.execGREP_ADD_SUB_REF(s); - }; - void fwdGREP_ADD_SUB_CONF(Signal* s){ - pspart.execGREP_ADD_SUB_CONF(s); - }; - - //CONF - void fwdSUB_CREATE_CONF(Signal* s) { - pspart.execSUB_CREATE_CONF(s); }; - void fwdSUB_START_CONF(Signal* s) { - pspart.execSUB_START_CONF(s); }; - void fwdSUB_REMOVE_CONF(Signal* s) { - pspart.execSUB_REMOVE_CONF(s); }; - void fwdSUB_SYNC_CONF(Signal* s) { - pspart.execSUB_SYNC_CONF(s); }; - - //REF - - void fwdSUB_CREATE_REF(Signal* s) { - pspart.execSUB_CREATE_REF(s); }; - void fwdSUB_START_REF(Signal* s) { - pspart.execSUB_START_REF(s); }; - void fwdSUB_REMOVE_REF(Signal* s) { - pspart.execSUB_REMOVE_REF(s); }; - void fwdSUB_SYNC_REF(Signal* s) { - pspart.execSUB_SYNC_REF(s); }; - - //REQ - void fwdSUB_SYNC_CONTINUE_REQ(Signal* s) { - pspart.execSUB_SYNC_CONTINUE_REQ(s); }; - void fwdGREP_CREATE_REQ(Signal* s) { - pspart.execGREP_CREATE_REQ(s); }; - void fwdGREP_START_REQ(Signal* s) { - pspart.execGREP_START_REQ(s); }; - void fwdGREP_SYNC_REQ(Signal* s) { - pspart.execGREP_SYNC_REQ(s); }; - void fwdGREP_REMOVE_REQ(Signal* s) { - pspart.execGREP_REMOVE_REQ(s); }; - - void fwdSUB_META_DATA(Signal* s) { - pspart.execSUB_META_DATA(s); }; - void fwdSUB_TABLE_DATA(Signal* s) { - pspart.execSUB_TABLE_DATA(s); }; - - void fwdSUB_GCP_COMPLETE_REP(Signal* s) { - pspart.execSUB_GCP_COMPLETE_REP(s); }; - - void sendEventRep(Signal * signal, - EventReport::EventType type, - GrepEvent::Subscription event, - Uint32 subId, - Uint32 subKey, - Uint32 err, - Uint32 gci=0); - - void getNodeGroupMembers(Signal* signal); - - - /*************************************************************************** - * Block Data - ***************************************************************************/ - struct Node { - Uint32 nodeId; - Uint32 alive; - Uint32 nextList; - union { Uint32 prevList; Uint32 nextPool; }; - }; - typedef Ptr NodePtr; - - NodeId m_masterNodeId; - SLList m_nodes; - NdbNodeBitmask m_aliveNodes; - ArrayPool m_nodePool; - - /** - * for all Suma's to keep track of other Suma's in Node group - */ - Uint32 c_nodeGroup; - Uint32 c_noNodesInGroup; - Uint32 c_idInNodeGroup; - NodeId c_nodesInGroup[4]; - - -public: - /*************************************************************************** - * GREP PS Coordinator - ***************************************************************************/ - class PSCoord : public BlockComponent { - - private: - - struct SubCoordinator { - Uint32 m_subscriberRef; - Uint32 m_subscriberData; - Uint32 m_coordinatorRef; - Uint32 m_subscriptionId; - Uint32 m_subscriptionKey; - Uint32 m_subscriptionType; - NdbNodeBitmask m_participants; - Uint32 m_outstandingRequest; - SignalCounter m_outstandingParticipants; - - Uint32 nextHash; - union { Uint32 prevHash; Uint32 nextPool; }; - - Uint32 hashValue() const { - return m_subscriptionId + m_subscriptionKey; - } - - bool equal(const SubCoordinator & s) const { - return - m_subscriptionId == s.m_subscriptionId && - m_subscriptionKey == s.m_subscriptionKey; - } - - }; - - typedef Ptr SubCoordinatorPtr; - ArrayPool c_subCoordinatorPool; - DLHashTable::Iterator c_subPtr; - DLHashTable c_runningSubscriptions; - - void prepareOperationRec(SubCoordinatorPtr ptr, - BlockReference subscriber, - Uint32 subId, - Uint32 subKey, - Uint32 request); - - public: - PSCoord(class Grep *); - - void execGREP_CREATE_CONF(Signal*); - void execGREP_START_CONF(Signal*); - void execGREP_SYNC_CONF(Signal*); - void execGREP_REMOVE_CONF(Signal*); - - void execGREP_CREATE_REF(Signal*); - void execGREP_START_REF(Signal*); - void execGREP_SYNC_REF(Signal*); - void execGREP_REMOVE_REF(Signal*); - - - void execCREATE_SUBID_CONF(Signal*); //comes from SUMA - void execGREP_CREATE_SUBID_REQ(Signal*); - - void execGREP_SUB_CREATE_REQ(Signal*); - void execGREP_SUB_START_REQ(Signal*); - void execGREP_SUB_SYNC_REQ(Signal*); - void execGREP_SUB_REMOVE_REQ(Signal*); - - - - void execCREATE_SUBID_REF(Signal*); - - - - void sendCreateSubIdRef_SS(Signal * signal, - Uint32 subId, - Uint32 subKey, - BlockReference to, - GrepError::GE_Code err); - - - void sendSubRemoveRef_SS(Signal * signal, - SubCoordinator sub, - GrepError::GE_Code err); - - void sendRefToSS(Signal * signal, - SubCoordinator sub, - GrepError::GE_Code err, - SubscriptionData::Part part = (SubscriptionData::Part)0); - - void setRepRef(BlockReference rr) { m_repRef = rr; }; - //void setAliveNodes(NdbNodeBitmask an) { m_aliveNodes = an; }; - - BlockReference m_repRef; ///< Rep node (only one rep node per grep) - // NdbNodeBitmask m_aliveNodes; - - Uint32 m_outstandingRequest; - SignalCounter m_outstandingParticipants; - - Grep * m_grep; - } pscoord; - friend class PSCoord; - - /*************************************************************************** - * GREP PS Participant - *************************************************************************** - * Participant of GREP Protocols (not necessarily a protocol coordinator) - * - * This object is only used on primary system - ***************************************************************************/ - class PSPart: public BlockComponent - { - //protected: - //GrepParticipant(const Configuration & conf); - //virtual ~GrepParticipant(); - //BLOCK_DEFINES(GrepParticipant); - - struct Subscription { - Uint32 m_subscriberRef; - Uint32 m_subscriberData; - Uint32 m_subscriptionId; - Uint32 m_subscriptionKey; - Uint32 m_subscriptionType; - Uint32 m_coordinatorRef; - Uint32 m_outstandingRequest; - Uint32 m_operationPtrI; - Uint32 nextHash; - union { Uint32 prevHash; Uint32 nextPool; }; - - Uint32 hashValue() const { - return m_subscriptionId + m_subscriptionKey; - } - - bool equal(const Subscription & s) const { - return - m_subscriptionId == s.m_subscriptionId && - m_subscriptionKey == s.m_subscriptionKey; - } - - }; - typedef Ptr SubscriptionPtr; - - DLHashTable c_subscriptions; - DLHashTable::Iterator c_subPtr; - ArrayPool c_subscriptionPool; - - public: - PSPart(class Grep *); - - - //protected: - /************************************************************************* - * SUMA Signal Interface - *************************************************************************/ - void execSUB_CREATE_CONF(Signal*); - void execSUB_START_CONF(Signal*); - void execSUB_SYNC_CONF(Signal*); - void execSUB_REMOVE_CONF(Signal*); - - void execSUB_CREATE_REF(Signal*); - void execSUB_START_REF(Signal*); - void execSUB_SYNC_REF(Signal*); - void execSUB_REMOVE_REF(Signal*); - - - void execSUB_META_DATA(Signal*); - void execSUB_TABLE_DATA(Signal*); - - - void execSUB_GCP_COMPLETE_REP(Signal*); - void execSUB_SYNC_CONTINUE_REQ(Signal*); - - /************************************************************************* - * GREP Coordinator Signal Interface - *************************************************************************/ - void execGREP_CREATE_REQ(Signal*); - void execGREP_START_REQ(Signal*); - void execGREP_SYNC_REQ(Signal*); - void execGREP_REMOVE_REQ(Signal*); - - /** - * NR/NF signals - */ - void execSTART_ME(Signal *); - void execGREP_ADD_SUB_REQ(Signal *); - void execGREP_ADD_SUB_REF(Signal *); - void execGREP_ADD_SUB_CONF(Signal *); - - /************************************************************************* - * GREP Coordinator error handling interface - *************************************************************************/ - - void sendRefToPSCoord(Signal * signal, - Subscription sub, - GrepError::GE_Code err, - SubscriptionData::Part part = (SubscriptionData::Part)0); - - //protected: - BlockReference m_repRef; ///< Replication node - ///< (only one rep node per grep) - bool m_recoveryMode; - - private: - BlockReference m_coordinator; - Uint32 m_firstScanGCI; - Uint32 m_lastScanGCI; - Uint32 m_latestSeenGCI; - Grep * m_grep; - } pspart; - friend class PSPart; - - /*************************************************************************** - * AddRecSignal Stuff (should maybe be gerneralized) - ***************************************************************************/ - typedef void (Grep::* ExecSignalLocal1) (Signal* signal); - typedef void (Grep::PSCoord::* ExecSignalLocal2) (Signal* signal); - typedef void (Grep::PSPart::* ExecSignalLocal4) (Signal* signal); -}; - - -/************************************************************************* - * Requestor - * - * The following methods are callbacks (registered functions) - * for the Requestor. The Requestor calls these when it needs - * something to be done. - *************************************************************************/ -void startSubscription(void * cbObj, Signal*, int type); -void scanSubscription(void * cbObj, Signal*, int type); - -#endif diff --git a/ndb/src/kernel/blocks/grep/GrepInit.cpp b/ndb/src/kernel/blocks/grep/GrepInit.cpp deleted file mode 100644 index d764fb1f473..00000000000 --- a/ndb/src/kernel/blocks/grep/GrepInit.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "Grep.hpp" -#include -#include - -/***************************************************************************** - * Grep Participant - *****************************************************************************/ -#if 0 -GrepParticipant::GrepParticipant(const Configuration & conf) : - SimulatedBlock(GREP, conf) -{ - BLOCK_CONSTRUCTOR(Grep); - //m_repRef = 0; - m_latestSeenGCI = 0; -} - -GrepParticipant::~GrepParticipant() -{ -} - -BLOCK_FUNCTIONS(GrepParticipant); -#endif - -/***************************************************************************** - * Grep Coordinator - *****************************************************************************/ -Grep::Grep(const Configuration & conf) : - // GrepParticipant(conf), - SimulatedBlock(GREP, conf), - m_nodes(m_nodePool), - pscoord(this), - pspart(this) -{ - m_nodePool.setSize(MAX_NDB_NODES); - m_masterNodeId = getOwnNodeId(); - - /*************************************************************************** - * General Signals - ***************************************************************************/ - addRecSignal(GSN_STTOR, &Grep::execSTTOR); - addRecSignal(GSN_NDB_STTOR, &Grep::execNDB_STTOR); - addRecSignal(GSN_DUMP_STATE_ORD, &Grep::execDUMP_STATE_ORD); - addRecSignal(GSN_READ_NODESCONF, &Grep::execREAD_NODESCONF); - addRecSignal(GSN_NODE_FAILREP, &Grep::execNODE_FAILREP); - addRecSignal(GSN_INCL_NODEREQ, &Grep::execINCL_NODEREQ); - - addRecSignal(GSN_GREP_REQ, &Grep::execGREP_REQ); - addRecSignal(GSN_API_FAILREQ, &Grep::execAPI_FAILREQ); - - - /*************************************************************************** - * Grep::PSCoord Signal Interface - ***************************************************************************/ - /** - * From Grep::PSPart - */ - addRecSignal(GSN_GREP_CREATE_CONF, &Grep::fwdGREP_CREATE_CONF); - addRecSignal(GSN_GREP_START_CONF, &Grep::fwdGREP_START_CONF); - addRecSignal(GSN_GREP_SYNC_CONF, &Grep::fwdGREP_SYNC_CONF); - addRecSignal(GSN_GREP_REMOVE_CONF, &Grep::fwdGREP_REMOVE_CONF); - - addRecSignal(GSN_GREP_CREATE_REF, &Grep::fwdGREP_CREATE_REF); - addRecSignal(GSN_GREP_START_REF, &Grep::fwdGREP_START_REF); - addRecSignal(GSN_GREP_REMOVE_REF, &Grep::fwdGREP_REMOVE_REF); - - /** - * From Grep::SSCoord to Grep::PSCoord - */ - addRecSignal(GSN_GREP_SUB_START_REQ, &Grep::fwdGREP_SUB_START_REQ); - addRecSignal(GSN_GREP_SUB_CREATE_REQ, &Grep::fwdGREP_SUB_CREATE_REQ); - addRecSignal(GSN_GREP_SUB_SYNC_REQ, &Grep::fwdGREP_SUB_SYNC_REQ); - addRecSignal(GSN_GREP_SUB_REMOVE_REQ, &Grep::fwdGREP_SUB_REMOVE_REQ); - addRecSignal(GSN_GREP_CREATE_SUBID_REQ, &Grep::fwdGREP_CREATE_SUBID_REQ); - - /**************************************************************************** - * PSPart - ***************************************************************************/ - /** - * From SUMA to GREP PS Participant. If suma is not a coodinator - */ - addRecSignal(GSN_SUB_START_CONF, &Grep::fwdSUB_START_CONF); - addRecSignal(GSN_SUB_CREATE_CONF, &Grep::fwdSUB_CREATE_CONF); - addRecSignal(GSN_SUB_SYNC_CONF, &Grep::fwdSUB_SYNC_CONF); - addRecSignal(GSN_SUB_REMOVE_CONF, &Grep::fwdSUB_REMOVE_CONF); - addRecSignal(GSN_SUB_CREATE_REF, &Grep::fwdSUB_CREATE_REF); - addRecSignal(GSN_SUB_START_REF, &Grep::fwdSUB_START_REF); - addRecSignal(GSN_SUB_SYNC_REF, &Grep::fwdSUB_SYNC_REF); - addRecSignal(GSN_SUB_REMOVE_REF, &Grep::fwdSUB_REMOVE_REF); - - addRecSignal(GSN_SUB_SYNC_CONTINUE_REQ, - &Grep::fwdSUB_SYNC_CONTINUE_REQ); - - /** - * From Suma to Grep::PSPart. Data signals. - */ - addRecSignal(GSN_SUB_META_DATA, &Grep::fwdSUB_META_DATA); - addRecSignal(GSN_SUB_TABLE_DATA, &Grep::fwdSUB_TABLE_DATA); - addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Grep::fwdSUB_GCP_COMPLETE_REP); - - /** - * From Grep::PSCoord to Grep::PSPart - */ - addRecSignal(GSN_GREP_CREATE_REQ, &Grep::fwdGREP_CREATE_REQ); - addRecSignal(GSN_GREP_START_REQ, &Grep::fwdGREP_START_REQ); - addRecSignal(GSN_GREP_REMOVE_REQ, &Grep::fwdGREP_REMOVE_REQ); - addRecSignal(GSN_GREP_SYNC_REQ, &Grep::fwdGREP_SYNC_REQ); - addRecSignal(GSN_CREATE_SUBID_CONF, &Grep::fwdCREATE_SUBID_CONF); - addRecSignal(GSN_GREP_START_ME, &Grep::fwdSTART_ME); - addRecSignal(GSN_GREP_ADD_SUB_REQ, &Grep::fwdGREP_ADD_SUB_REQ); - addRecSignal(GSN_GREP_ADD_SUB_REF, &Grep::fwdGREP_ADD_SUB_REF); - addRecSignal(GSN_GREP_ADD_SUB_CONF, &Grep::fwdGREP_ADD_SUB_CONF); -} - -Grep::~Grep() -{ -} - -BLOCK_FUNCTIONS(Grep) - -Grep::PSPart::PSPart(Grep * sb) : - BlockComponent(sb), - c_subscriptions(c_subscriptionPool) -{ - m_grep = sb; - - m_firstScanGCI = 1; // Empty interval = [1,0] - m_lastScanGCI = 0; - - m_latestSeenGCI = 0; - - c_subscriptions.setSize(10); - c_subscriptionPool.setSize(10); -} - -Grep::PSCoord::PSCoord(Grep * sb) : - BlockComponent(sb), - c_runningSubscriptions(c_subCoordinatorPool) -{ - m_grep = sb; - c_runningSubscriptions.setSize(10); - c_subCoordinatorPool.setSize(2); -} - -//BLOCK_FUNCTIONS(Grep::PSCoord); - -BlockComponent::BlockComponent(SimulatedBlock * sb) { - m_sb = sb; -} diff --git a/ndb/src/kernel/blocks/grep/Makefile.am b/ndb/src/kernel/blocks/grep/Makefile.am deleted file mode 100644 index 6d2b422784b..00000000000 --- a/ndb/src/kernel/blocks/grep/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -noinst_LIBRARIES = libgrep.a - -libgrep_a_SOURCES = Grep.cpp GrepInit.cpp - -include $(top_srcdir)/ndb/config/common.mk.am -include $(top_srcdir)/ndb/config/type_kernel.mk.am - -# Don't update the files from bitkeeper -%::SCCS/s.% - -windoze-dsp: libgrep.dsp - -libgrep.dsp: Makefile \ - $(top_srcdir)/ndb/config/win-lib.am \ - $(top_srcdir)/ndb/config/win-name \ - $(top_srcdir)/ndb/config/win-includes \ - $(top_srcdir)/ndb/config/win-sources \ - $(top_srcdir)/ndb/config/win-libraries - cat $(top_srcdir)/ndb/config/win-lib.am > $@ - @$(top_srcdir)/ndb/config/win-name $@ $(noinst_LIBRARIES) - @$(top_srcdir)/ndb/config/win-includes $@ $(INCLUDES) - @$(top_srcdir)/ndb/config/win-sources $@ $(libgrep_a_SOURCES) - @$(top_srcdir)/ndb/config/win-libraries $@ LIB $(LDADD) diff --git a/ndb/src/kernel/blocks/grep/systab_test/Makefile b/ndb/src/kernel/blocks/grep/systab_test/Makefile deleted file mode 100644 index bd69e0f3799..00000000000 --- a/ndb/src/kernel/blocks/grep/systab_test/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -TYPE := kernel - -BIN_TARGET := grep_systab_test -BIN_TARGET_ARCHIVES := portlib general - -CCFLAGS_LOC += -I.. - -SOURCES = ../GrepSystemTable.cpp grep_systab_test.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/grep/systab_test/grep_systab_test.cpp b/ndb/src/kernel/blocks/grep/systab_test/grep_systab_test.cpp deleted file mode 100644 index e3a77af4e4e..00000000000 --- a/ndb/src/kernel/blocks/grep/systab_test/grep_systab_test.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/** - * Unit Test for GrepSystemTable - */ - -#include "../GrepSystemTable.hpp" -#include - -#define EXEC(X) ( ndbout << endl, ndbout_c(#X), X ) - -int -main () { - GrepSystemTable st; - - Uint32 f, l; - - ndbout_c("*************************************"); - ndbout_c("* GrepSystemTable Unit Test Program *"); - ndbout_c("*************************************"); - - ndbout_c("--------------------------------------------------------"); - ndbout_c("Test 1: Clear"); - ndbout_c("--------------------------------------------------------"); - - EXEC(st.set(GrepSystemTable::PS, 22, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - - EXEC(st.clear(GrepSystemTable::PS, 20, 24)); - st.print(); - st.require(GrepSystemTable::PS, 25, 26); - - EXEC(st.clear(GrepSystemTable::PS, 0, 100)); - st.print(); - st.require(GrepSystemTable::PS, 1, 0); - - EXEC(st.set(GrepSystemTable::PS, 22, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - - EXEC(st.clear(GrepSystemTable::PS, 24, 28)); - st.print(); - st.require(GrepSystemTable::PS, 22, 23); - - EXEC(st.clear(GrepSystemTable::PS, 0, 100)); - st.print(); - st.require(GrepSystemTable::PS, 1, 0); - - EXEC(st.set(GrepSystemTable::PS, 22, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - - EXEC(st.clear(GrepSystemTable::PS, 24, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 23); - - EXEC(st.clear(GrepSystemTable::PS, 0, 100)); - st.print(); - st.require(GrepSystemTable::PS, 1, 0); - - EXEC(st.set(GrepSystemTable::PS, 22, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - - EXEC(st.clear(GrepSystemTable::PS, 22, 24)); - st.print(); - st.require(GrepSystemTable::PS, 25, 26); - - ndbout_c("--------------------------------------------------------"); - ndbout_c("Test 2: PS --> SSreq"); - ndbout_c("--------------------------------------------------------"); - - EXEC(st.set(GrepSystemTable::PS, 22, 26)); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - st.require(GrepSystemTable::SSReq, 1, 0); - - if (!EXEC(st.copy(GrepSystemTable::PS, GrepSystemTable::SSReq, 3, &f, &l))) - ndbout_c("%s:%d: Illegal copy!", __FILE__, __FILE__); - ndbout_c("f=%d, l=%d", f, l); - st.print(); - st.require(GrepSystemTable::PS, 22, 26); - st.require(GrepSystemTable::SSReq, 22, 24); - - EXEC(st.clear(GrepSystemTable::PS, 22, 22)); - st.print(); - st.require(GrepSystemTable::PS, 23, 26); - st.require(GrepSystemTable::SSReq, 22, 24); - - if (!EXEC(st.copy(GrepSystemTable::PS, GrepSystemTable::SSReq, 2, &f, &l))) - ndbout_c("%s:%d: Illegal copy!", __FILE__, __LINE__); - ndbout_c("f=%d, l=%d", f, l); - st.print(); - st.require(GrepSystemTable::PS, 23, 26); - st.require(GrepSystemTable::SSReq, 22, 26); - - st.set(GrepSystemTable::SS, 7, 9); - st.set(GrepSystemTable::InsReq, 7, 9); - if (EXEC(st.movable(GrepSystemTable::SS, GrepSystemTable::InsReq))) - ndbout_c("%s:%d: Illegal move!", __FILE__, __LINE__); - st.print(); - st.require(GrepSystemTable::SS, 7, 9); - st.require(GrepSystemTable::InsReq, 7, 9); - - EXEC(st.intervalMinus(7, 9, 7, 7, &f, &l)); - ndbout_c("f=%d, l=%d", f, l); - - st.clear(GrepSystemTable::InsReq, 8, 9); - st.require(GrepSystemTable::SS, 7, 9); - st.require(GrepSystemTable::InsReq, 7, 7); - if (EXEC(st.movable(GrepSystemTable::SS, GrepSystemTable::InsReq)) != 2) - ndbout_c("%s:%d: Illegal move!", __FILE__, __LINE__); - st.print(); - - EXEC(st.copy(GrepSystemTable::SS, GrepSystemTable::InsReq, &f)); - st.print(); - st.require(GrepSystemTable::SS, 7, 9); - st.require(GrepSystemTable::InsReq, 7, 8); - - ndbout_c("--------------------------------------------------------"); - ndbout_c("Test completed"); - ndbout_c("--------------------------------------------------------"); -} diff --git a/ndb/test/ndbapi/testGrep.cpp b/ndb/test/ndbapi/testGrep.cpp deleted file mode 100644 index 713aefbeafa..00000000000 --- a/ndb/test/ndbapi/testGrep.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include -#include -#include -#include -#include - - -#define CHECK(b) if (!(b)) { \ - g_err << "ERR: "<< step->getName() \ - << " failed on line " << __LINE__ << endl; \ - result = NDBT_FAILED; \ - continue; } - - -int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ - - int records = ctx->getNumRecords(); - HugoTransactions hugoTrans(*ctx->getTab()); - if (hugoTrans.loadTable(GETNDB(step), records) != 0){ - return NDBT_FAILED; - } - return NDBT_OK; -} - -int runPkUpdate(NDBT_Context* ctx, NDBT_Step* step){ - int loops = ctx->getNumLoops(); - int records = ctx->getNumRecords(); - int batchSize = ctx->getProperty("BatchSize", 1); - int i = 0; - HugoTransactions hugoTrans(*ctx->getTab()); - while (igetTab(); - pNdb->getDictionary()->dropTable(tab->getName()); - - if (restarter.restartAll(true) != 0) - return NDBT_FAILED; - - return NDBT_OK; -} - -int runRestarter(NDBT_Context* ctx, NDBT_Step* step){ - int result = NDBT_OK; - int loops = ctx->getNumLoops(); - NdbRestarter restarter; - int i = 0; - int lastId = 0; - - if (restarter.getNumDbNodes() < 2){ - ctx->stopTest(); - return NDBT_OK; - } - - if(restarter.waitClusterStarted(60) != 0){ - g_err << "Cluster failed to start" << endl; - return NDBT_FAILED; - } - - loops *= restarter.getNumDbNodes(); - while(iisTestStopped()){ - - int id = lastId % restarter.getNumDbNodes(); - int nodeId = restarter.getDbNodeId(id); - ndbout << "Restart node " << nodeId << endl; - if(restarter.restartOneDbNode(nodeId) != 0){ - g_err << "Failed to restartNextDbNode" << endl; - result = NDBT_FAILED; - break; - } - - if(restarter.waitClusterStarted(60) != 0){ - g_err << "Cluster failed to start" << endl; - result = NDBT_FAILED; - break; - } - - NdbSleep_SecSleep(1); - - lastId++; - i++; - } - - ctx->stopTest(); - - return result; -} - -int runCheckAllNodesStarted(NDBT_Context* ctx, NDBT_Step* step){ - NdbRestarter restarter; - - if(restarter.waitClusterStarted(1) != 0){ - g_err << "All nodes was not started " << endl; - return NDBT_FAILED; - } - - return NDBT_OK; -} - - -bool testMaster = true; -bool testSlave = false; - -int setMaster(NDBT_Context* ctx, NDBT_Step* step){ - testMaster = true; - testSlave = false; - return NDBT_OK; -} -int setMasterAsSlave(NDBT_Context* ctx, NDBT_Step* step){ - testMaster = true; - testSlave = true; - return NDBT_OK; -} -int setSlave(NDBT_Context* ctx, NDBT_Step* step){ - testMaster = false; - testSlave = true; - return NDBT_OK; -} - -int runAbort(NDBT_Context* ctx, NDBT_Step* step){ - - - NdbGrep grep(GETNDB(step)->getNodeId()+1); - NdbRestarter restarter; - - if (restarter.getNumDbNodes() < 2){ - ctx->stopTest(); - return NDBT_OK; - } - - if(restarter.waitClusterStarted(60) != 0){ - g_err << "Cluster failed to start" << endl; - return NDBT_FAILED; - } - - if (testMaster) { - if (testSlave) { - if (grep.NFMasterAsSlave(restarter) == -1){ - return NDBT_FAILED; - } - } else { - if (grep.NFMaster(restarter) == -1){ - return NDBT_FAILED; - } - } - } else { - if (grep.NFSlave(restarter) == -1){ - return NDBT_FAILED; - } - } - - return NDBT_OK; -} - -int runFail(NDBT_Context* ctx, NDBT_Step* step){ - NdbGrep grep(GETNDB(step)->getNodeId()+1); - - NdbRestarter restarter; - - if (restarter.getNumDbNodes() < 2){ - ctx->stopTest(); - return NDBT_OK; - } - - if(restarter.waitClusterStarted(60) != 0){ - g_err << "Cluster failed to start" << endl; - return NDBT_FAILED; - } - - if (testMaster) { - if (testSlave) { - if (grep.FailMasterAsSlave(restarter) == -1){ - return NDBT_FAILED; - } - } else { - if (grep.FailMaster(restarter) == -1){ - return NDBT_FAILED; - } - } - } else { - if (grep.FailSlave(restarter) == -1){ - return NDBT_FAILED; - } - } - - return NDBT_OK; -} - -int runGrepBasic(NDBT_Context* ctx, NDBT_Step* step){ - NdbGrep grep(GETNDB(step)->getNodeId()+1); - unsigned grepId = 0; - - if (grep.start() == -1){ - return NDBT_FAILED; - } - ndbout << "Started grep " << grepId << endl; - ctx->setProperty("GrepId", grepId); - - return NDBT_OK; -} - - - - -int runVerifyBasic(NDBT_Context* ctx, NDBT_Step* step){ - NdbGrep grep(GETNDB(step)->getNodeId()+1, ctx->getRemoteMgm()); - ndbout_c("no of nodes %d" ,grep.getNumDbNodes()); - int result; - if ((result = grep.verify(ctx)) == -1){ - return NDBT_FAILED; - } - return result; -} - - - -int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ - int records = ctx->getNumRecords(); - - UtilTransactions utilTrans(*ctx->getTab()); - if (utilTrans.clearTable2(GETNDB(step), records) != 0){ - return NDBT_FAILED; - } - return NDBT_OK; -} - -#include "bank/Bank.hpp" - -int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - int overWriteExisting = true; - if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK) - return NDBT_FAILED; - return NDBT_OK; -} - -int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - int wait = 30; // Max seconds between each "day" - int yield = 1; // Loops before bank returns - - while (ctx->isTestStopped() == false) { - bank.performIncreaseTime(wait, yield); - } - return NDBT_OK; -} - -int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - int wait = 10; // Max ms between each transaction - int yield = 100; // Loops before bank returns - - while (ctx->isTestStopped() == false) { - bank.performTransactions(wait, yield); - } - return NDBT_OK; -} - -int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - int yield = 20; // Loops before bank returns - int result = NDBT_OK; - - while (ctx->isTestStopped() == false) { - if (bank.performMakeGLs(yield) != NDBT_OK){ - ndbout << "bank.performMakeGLs FAILED" << endl; - result = NDBT_FAILED; - } - } - return NDBT_OK; -} - -int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - int wait = 2000; // Max ms between each sum of accounts - int yield = 1; // Loops before bank returns - int result = NDBT_OK; - - while (ctx->isTestStopped() == false) { - if (bank.performSumAccounts(wait, yield) != NDBT_OK){ - ndbout << "bank.performSumAccounts FAILED" << endl; - result = NDBT_FAILED; - } - } - return result ; -} - -int runDropBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; - if (bank.dropBank() != NDBT_OK) - return NDBT_FAILED; - return NDBT_OK; -} - -int runGrepBank(NDBT_Context* ctx, NDBT_Step* step){ - int loops = ctx->getNumLoops(); - int l = 0; - int maxSleep = 30; // Max seconds between each grep - Ndb* pNdb = GETNDB(step); - NdbGrep grep(GETNDB(step)->getNodeId()+1); - unsigned minGrepId = ~0; - unsigned maxGrepId = 0; - unsigned grepId = 0; - int result = NDBT_OK; - - while (l < loops && result != NDBT_FAILED){ - - if (pNdb->waitUntilReady() != 0){ - result = NDBT_FAILED; - continue; - } - - // Sleep for a while - NdbSleep_SecSleep(maxSleep); - - // Perform grep - if (grep.start() != 0){ - ndbout << "grep.start failed" << endl; - result = NDBT_FAILED; - continue; - } - ndbout << "Started grep " << grepId << endl; - - // Remember min and max grepid - if (grepId < minGrepId) - minGrepId = grepId; - - if (grepId > maxGrepId) - maxGrepId = grepId; - - ndbout << " maxGrepId = " << maxGrepId - << ", minGrepId = " << minGrepId << endl; - ctx->setProperty("MinGrepId", minGrepId); - ctx->setProperty("MaxGrepId", maxGrepId); - - l++; - } - - ctx->stopTest(); - - return result; -} -/* -int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ - NdbRestarter restarter; - NdbGrep grep(GETNDB(step)->getNodeId()+1); - unsigned minGrepId = ctx->getProperty("MinGrepId"); - unsigned maxGrepId = ctx->getProperty("MaxGrepId"); - unsigned grepId = minGrepId; - int result = NDBT_OK; - int errSumAccounts = 0; - int errValidateGL = 0; - - ndbout << " maxGrepId = " << maxGrepId << endl; - ndbout << " minGrepId = " << minGrepId << endl; - - while (grepId <= maxGrepId){ - - // TEMPORARY FIX - // To erase all tables from cache(s) - // To be removed, maybe replaced by ndb.invalidate(); - { - Bank bank; - - if (bank.dropBank() != NDBT_OK){ - result = NDBT_FAILED; - break; - } - } - // END TEMPORARY FIX - - ndbout << "Performing initial restart" << endl; - if (restarter.restartAll(true) != 0) - return NDBT_FAILED; - - if (restarter.waitClusterStarted() != 0) - return NDBT_FAILED; - - ndbout << "Restoring grep " << grepId << endl; - if (grep.restore(grepId) == -1){ - return NDBT_FAILED; - } - ndbout << "Grep " << grepId << " restored" << endl; - - // Let bank verify - Bank bank; - - int wait = 0; - int yield = 1; - if (bank.performSumAccounts(wait, yield) != 0){ - ndbout << "bank.performSumAccounts FAILED" << endl; - ndbout << " grepId = " << grepId << endl << endl; - result = NDBT_FAILED; - errSumAccounts++; - } - - if (bank.performValidateAllGLs() != 0){ - ndbout << "bank.performValidateAllGLs FAILED" << endl; - ndbout << " grepId = " << grepId << endl << endl; - result = NDBT_FAILED; - errValidateGL++; - } - - grepId++; - } - - if (result != NDBT_OK){ - ndbout << "Verification of grep failed" << endl - << " errValidateGL="< Date: Tue, 23 Aug 2005 13:01:46 +0200 Subject: [PATCH 46/80] configure.in: fixed build bug with ndb grep block configure.in: fixed build bug with ndb grep block --- configure.in | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.in b/configure.in index ffd6fc3f483..4aef78e5b18 100644 --- a/configure.in +++ b/configure.in @@ -2755,7 +2755,6 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl ndb/src/kernel/blocks/backup/Makefile dnl ndb/src/kernel/blocks/dbutil/Makefile dnl ndb/src/kernel/blocks/suma/Makefile dnl - ndb/src/kernel/blocks/grep/Makefile dnl ndb/src/kernel/blocks/dbtux/Makefile dnl ndb/src/kernel/vm/Makefile dnl ndb/src/mgmapi/Makefile dnl From 51d1c2ad4cce62b121b83ab309b4aab22c72af74 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 13:57:12 +0200 Subject: [PATCH 47/80] tests fixes mysql-test/lib/init_db.sql: this should be longblob or info_schema test will fail mysql-test/r/rpl_delete_all.result: fix result of a test, the error message is different (bug #12591) mysql-test/t/rpl_delete_all.test: fix test, now the error code is different (bug #12591) --- mysql-test/lib/init_db.sql | 2 +- mysql-test/r/rpl_delete_all.result | 2 +- mysql-test/t/rpl_delete_all.test | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index a71de229ee9..37353e5974f 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -518,7 +518,7 @@ CREATE TABLE proc ( security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, - body blob DEFAULT '' NOT NULL, + body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, diff --git a/mysql-test/r/rpl_delete_all.result b/mysql-test/r/rpl_delete_all.result index 5ed221823e8..1aa556270c9 100644 --- a/mysql-test/r/rpl_delete_all.result +++ b/mysql-test/r/rpl_delete_all.result @@ -9,7 +9,7 @@ drop database if exists mysqltest; Warnings: Note 1008 Can't drop database 'mysqltest'; database doesn't exist show tables from mysqltest; -ERROR HY000: Can't read dir of './mysqltest/' (Errcode: X) +ERROR 42000: Unknown database 'mysqltest' create table t1 (a int); drop table if exists t1; Warnings: diff --git a/mysql-test/t/rpl_delete_all.test b/mysql-test/t/rpl_delete_all.test index db33ee3bb86..e0c0757bbc2 100644 --- a/mysql-test/t/rpl_delete_all.test +++ b/mysql-test/t/rpl_delete_all.test @@ -7,7 +7,7 @@ drop database if exists mysqltest; sync_slave_with_master; # can't read dir --replace_result "Errcode: 1" "Errcode: X" "Errcode: 2" "Errcode: X" \\ / ---error 12 +--error 1049 show tables from mysqltest; connection slave; From fe24add743df9dc2f8d72352e777c0f6f495d5fb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 18:08:04 +0300 Subject: [PATCH 48/80] WL#2486 - natural and using join according to SQL:2003 * Provide backwards compatibility extension to name resolution of coalesced columns. The patch allows such columns to be qualified with a table (and db) name, as it is in 4.1. Based on a patch from Monty. * Adjusted tests accordingly to test both backwards compatible name resolution of qualified columns, and ANSI-style resolution of non-qualified columns. For this, each affected test has two versions - one with qualified columns, and one without. mysql-test/include/ps_query.inc: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/bdb.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/innodb.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/join.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/join_nested.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/join_outer.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/null_key.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/order_by.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_2myisam.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_3innodb.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_4heap.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_5merge.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_6bdb.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/ps_7ndb.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/select.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/subselect.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/r/type_ranges.result: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/bdb.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/innodb.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/join.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/join_nested.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/join_outer.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/null_key.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/order_by.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/select.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/subselect.test: Put back old tests to test that coalesced columns of natural joins can be qualified. mysql-test/t/type_ranges.test: Put back old tests to test that coalesced columns of natural joins can be qualified. sql/sql_base.cc: * Applied Monty's patch for backwards compatible name resolution of qualified columns. The idea is: - When a column is qualified, search for the column in all tables/views underlying each natural join. In this case natural joins are *not* considered leaves. - If a column is not qualified, then consider natural joins as leaves, thus directly search the result columns of natural joins. * Simplified 'find_field_in_tables()' - unified two similar loops into one. sql/table.cc: - Removed method & members not needed after Monty's patch. sql/table.h: - Removed method & members not needed after Monty's patch. tests/mysql_client_test.c: Put back old tests to test that coalesced columns of natural joins can be qualified. --- mysql-test/include/ps_query.inc | 12 +- mysql-test/r/bdb.result | 7 +- mysql-test/r/innodb.result | 5 + mysql-test/r/join.result | 48 ++++--- mysql-test/r/join_nested.result | 10 +- mysql-test/r/join_outer.result | 112 ++++++++------- mysql-test/r/null_key.result | 14 +- mysql-test/r/order_by.result | 25 ++++ mysql-test/r/ps_2myisam.result | 24 ++-- mysql-test/r/ps_3innodb.result | 24 ++-- mysql-test/r/ps_4heap.result | 24 ++-- mysql-test/r/ps_5merge.result | 48 +++---- mysql-test/r/ps_6bdb.result | 24 ++-- mysql-test/r/ps_7ndb.result | 24 ++-- mysql-test/r/select.result | 38 +++++ mysql-test/r/subselect.result | 8 ++ mysql-test/r/type_ranges.result | 16 +++ mysql-test/t/bdb.test | 3 +- mysql-test/t/innodb.test | 1 + mysql-test/t/join.test | 15 +- mysql-test/t/join_nested.test | 2 +- mysql-test/t/join_outer.test | 20 +-- mysql-test/t/null_key.test | 16 +-- mysql-test/t/order_by.test | 13 ++ mysql-test/t/select.test | 13 ++ mysql-test/t/subselect.test | 2 + mysql-test/t/type_ranges.test | 7 + sql/sql_base.cc | 240 +++++++++++++------------------- sql/table.cc | 9 -- sql/table.h | 7 - tests/mysql_client_test.c | 4 +- 31 files changed, 458 insertions(+), 357 deletions(-) diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc index 97653c0b9f8..27a86f88231 100644 --- a/mysql-test/include/ps_query.inc +++ b/mysql-test/include/ps_query.inc @@ -349,14 +349,14 @@ drop table if exists t2 ; --enable_warnings create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; let $1= 9 ; while ($1) { diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index a0b68bfbc13..d525b019c64 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -732,6 +732,11 @@ drop table t1; set @a:=now(); CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=bdb; insert into t1 (a) values(1),(2),(3); +select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a; +a +1 +2 +3 select a from t1 natural join t1 as t2 where b >= @a order by a; a 1 @@ -906,7 +911,7 @@ create temporary table tmp1 select branch_id, target_id, platform_id, product_id from t1, t2, t3, t4 ; create temporary table tmp2 -select branch_id, target_id, platform_id, product_id +select tmp1.branch_id, tmp1.target_id, tmp1.platform_id, tmp1.product_id from tmp1 left join t8 using (branch_id,target_id,platform_id,product_id) where t8.archive_id is null ; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 91d72045169..4b62e63c49b 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -750,6 +750,11 @@ drop table t1; set @a:=now(); CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=innodb; insert into t1 (a) values(1),(2),(3); +select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a; +a +1 +2 +3 select a from t1 natural join t1 as t2 where b >= @a order by a; a 1 diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 5ea863b4bdb..c887dc9d6a7 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -121,6 +121,12 @@ id catid stateid countyid drop table t1, t2; create table t1 (a int primary key); insert into t1 values(1),(2); +select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a); +a +1 +2 +select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a); +ERROR HY000: Too many tables; MySQL can only use XX tables in a join select a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a); a 1 @@ -145,6 +151,10 @@ DROP TABLE t1, t2; CREATE TABLE t1 (d DATE NOT NULL); CREATE TABLE t2 (d DATE NOT NULL); INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00'); +SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL; +d +2001-08-01 +0000-00-00 SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE d IS NULL; d 0000-00-00 @@ -264,6 +274,12 @@ PRIMARY KEY (siteid,rate_code), FULLTEXT KEY rate_code (rate_code) ) ENGINE=MyISAM; INSERT INTO t2 VALUES ('rivercats','cust',20); +SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats'; +rate_code base_rate +cust 20 +SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; +rate_code base_rate +cust 20 SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND siteid = 'rivercats'; rate_code base_rate cust 20 @@ -326,7 +342,7 @@ select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i); i i i NULL NULL 1 2 2 2 -select * from t1,t2 natural left join t3 order by 1,2; +select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i; i i 1 2 1 3 @@ -338,36 +354,36 @@ i i i 1 3 NULL 2 2 2 2 3 NULL -select * from t2 natural left join t3,t1 order by t1.i; -i i -2 1 -3 1 -2 2 -3 2 +select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i; +i i i +1 2 2 +1 3 NULL +2 2 2 +2 3 NULL select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; i i i 1 2 2 1 3 NULL 2 2 2 2 3 NULL -select * from t1,t2 natural right join t3 order by 1,2; +select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i; i i -1 2 1 4 -2 2 +1 2 2 4 +2 2 select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; i i i 1 NULL 4 1 2 2 2 NULL 4 2 2 2 -select * from t2 natural right join t3,t1 order by t1.i; -i i -2 1 -4 1 -2 2 -4 2 +select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i; +i i i +1 NULL 4 +1 2 2 +2 NULL 4 +2 2 2 select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; i i i 1 NULL 4 diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result index 8779c61b686..f9a25898a6f 100644 --- a/mysql-test/r/join_nested.result +++ b/mysql-test/r/join_nested.result @@ -1153,13 +1153,13 @@ a b a1 b 4 2 1 2 4 2 2 2 5 3 NULL NULL -SELECT * +SELECT t2.a,t2.b,t3.a1,t3.b FROM t2 NATURAL LEFT JOIN t3 WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL); -b a c a1 c1 -2 4 0 1 0 -2 4 0 2 0 -3 5 0 NULL NULL +a b a1 b +4 2 1 2 +4 2 2 2 +5 3 NULL NULL DROP TABLE t0,t1,t2,t3,t4,t5,t6,t7,t8,t9; CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 9bc85dfa987..d4a20209162 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -36,16 +36,7 @@ grp a c id a c d 3 5 C 3 5 B 5 3 6 D 3 6 C 6 NULL NULL NULL 4 7 D 7 -select * from t1 left join t2 using (a); -a grp c id c d -1 1 a 1 a 1 -2 2 b NULL NULL NULL -3 2 c NULL NULL NULL -4 3 E 3 A 4 -5 3 C 3 B 5 -6 3 D 3 C 6 -NULL NULL NULL NULL NULL -select t1.*,t2.* from t1 left join t2 on t1.a=t2.a; +select t1.*,t2.* from t1 left join t2 using (a); grp a c id a c d 1 1 a 1 1 a 1 2 2 b NULL NULL NULL NULL @@ -54,34 +45,40 @@ grp a c id a c d 3 5 C 3 5 B 5 3 6 D 3 6 C 6 NULL NULL NULL NULL NULL NULL -select * from t1 left join t2 using (a,c); -a c grp id d -1 a 1 1 1 -2 b 2 NULL NULL -3 c 2 NULL NULL -4 E 3 NULL NULL -5 C 3 NULL NULL -6 D 3 NULL NULL -NULL NULL NULL NULL -select * from t1 left join t2 using (c); -c grp a id a d -a 1 1 1 1 1 -a 1 1 3 4 4 -b 2 2 3 5 5 -c 2 3 3 6 6 -E 3 4 NULL NULL NULL -C 3 5 3 6 6 -D 3 6 4 7 7 - NULL NULL NULL NULL NULL -select * from t1 natural left outer join t2; -a c grp id d -1 a 1 1 1 -2 b 2 NULL NULL -3 c 2 NULL NULL -4 E 3 NULL NULL -5 C 3 NULL NULL -6 D 3 NULL NULL -NULL NULL NULL NULL +select t1.*,t2.* from t1 left join t2 using (a) where t1.a=t2.a; +grp a c id a c d +1 1 a 1 1 a 1 +3 4 E 3 4 A 4 +3 5 C 3 5 B 5 +3 6 D 3 6 C 6 +select t1.*,t2.* from t1 left join t2 using (a,c); +grp a c id a c d +1 1 a 1 1 a 1 +2 2 b NULL NULL NULL NULL +2 3 c NULL NULL NULL NULL +3 4 E NULL NULL NULL NULL +3 5 C NULL NULL NULL NULL +3 6 D NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL +select t1.*,t2.* from t1 left join t2 using (c); +grp a c id a c d +1 1 a 1 1 a 1 +1 1 a 3 4 A 4 +2 2 b 3 5 B 5 +2 3 c 3 6 C 6 +3 4 E NULL NULL NULL NULL +3 5 C 3 6 C 6 +3 6 D 4 7 D 7 +NULL NULL NULL NULL NULL NULL +select t1.*,t2.* from t1 natural left outer join t2; +grp a c id a c d +1 1 a 1 1 a 1 +2 2 b NULL NULL NULL NULL +2 3 c NULL NULL NULL NULL +3 4 E NULL NULL NULL NULL +3 5 C NULL NULL NULL NULL +3 6 D NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) where t2.id=3; grp a c id a c d 3 4 E 3 4 A 4 @@ -114,21 +111,21 @@ select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on ERROR 42S22: Unknown column 't3.a' in 'on clause' select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a); ERROR 42S22: Unknown column 't3.a' in 'on clause' -select * from t1 inner join t2 using (a); -a grp c id c d -1 1 a 1 a 1 -4 3 E 3 A 4 -5 3 C 3 B 5 -6 3 D 3 C 6 +select t1.*,t2.* from t1 inner join t2 using (a); +grp a c id a c d +1 1 a 1 1 a 1 +3 4 E 3 4 A 4 +3 5 C 3 5 B 5 +3 6 D 3 6 C 6 select t1.*,t2.* from t1 inner join t2 on (t1.a=t2.a); grp a c id a c d 1 1 a 1 1 a 1 3 4 E 3 4 A 4 3 5 C 3 5 B 5 3 6 D 3 6 C 6 -select * from t1 natural join t2; -a c grp id d -1 a 1 1 1 +select t1.*,t2.* from t1 natural join t2; +grp a c id a c d +1 1 a 1 1 a 1 drop table t1,t2; CREATE TABLE t1 ( usr_id INT unsigned NOT NULL, @@ -435,7 +432,7 @@ INSERT INTO t2 VALUES (3,'z'); SELECT t2.id2 FROM t2 LEFT OUTER JOIN t1 ON t1.id2 = t2.id2 WHERE id1 IS NULL; id2 3 -SELECT id2 FROM t2 NATURAL LEFT OUTER JOIN t1 WHERE id1 IS NULL; +SELECT t2.id2 FROM t2 NATURAL LEFT OUTER JOIN t1 WHERE id1 IS NULL; id2 3 drop table t1,t2; @@ -653,6 +650,13 @@ select * from t1 natural left join t2 natural left join t3; i 1 2 +select * from t1 natural left join t2 where (t2.i is not null)=0; +i +1 +select * from t1 natural left join t2 where (t2.i is not null) is not null; +i +1 +2 select * from t1 natural left join t2 where (i is not null)=0; i select * from t1 natural left join t2 where (i is not null) is not null; @@ -931,6 +935,18 @@ create table t1 (a int, b varchar(20)); create table t2 (a int, c varchar(20)); insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb"); insert into t2 values (1,"cccccccccc"),(2,"dddddddddd"); +select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by t1.a; +group_concat(t1.b,t2.c) +aaaaa +bbbbb +Warnings: +Warning 1260 2 line(s) were cut by GROUP_CONCAT() +select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a; +group_concat(t1.b,t2.c) +aaaaa +bbbbb +Warnings: +Warning 1260 2 line(s) were cut by GROUP_CONCAT() select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a; group_concat(t1.b,t2.c) aaaaa diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 5c2141befa6..7f746a3dbd8 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -313,16 +313,12 @@ INSERT INTO t1 (order_id, product_id, product_type) VALUES ('9d9aad7764b5b2c53004348ef8d34500',2315652, 3); INSERT INTO t2 (order_id, product_id, product_type) VALUES ('9d9aad7764b5b2c53004348ef8d34500',2315652, 3); -select t1.* from t1 left join t2 -on (t1.order_id = t2.order_id and -t1.product_id = t2.product_id and -t1.product_type = t2.product_type) -where t2.order_id = NULL; +select t1.* from t1 +left join t2 using(order_id, product_id, product_type) +where t2.order_id=NULL; order_id product_id product_type -select t1.* from t1 left join t2 -on (t1.order_id = t2.order_id and -t1.product_id = t2.product_id and -t1.product_type = t2.product_type) +select t1.* from t1 +left join t2 using(order_id, product_id, product_type) where t2.order_id is NULL; order_id product_id product_type 3d7ce39b5d4b3e3d22aaafe9b633de51 1206029 3 diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index b766f146254..6864c35dbfc 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -180,6 +180,15 @@ INSERT INTO t3 VALUES (1,'123 Park Place'); INSERT INTO t3 VALUES (2,'453 Boardwalk'); SELECT a,b,if(b = 1,i,if(b = 2,v,'')) FROM t1 +LEFT JOIN t2 USING(c) +LEFT JOIN t3 ON t3.c = t1.c; +a b if(b = 1,i,if(b = 2,v,'')) +1 1 50 +2 1 25 +3 2 123 Park Place +4 2 453 Boardwalk +SELECT a,b,if(b = 1,i,if(b = 2,v,'')) +FROM t1 LEFT JOIN t2 ON t1.c = t2.c LEFT JOIN t3 ON t3.c = t1.c; a b if(b = 1,i,if(b = 2,v,'')) @@ -189,6 +198,16 @@ a b if(b = 1,i,if(b = 2,v,'')) 4 2 453 Boardwalk SELECT a,b,if(b = 1,i,if(b = 2,v,'')) FROM t1 +LEFT JOIN t2 USING(c) +LEFT JOIN t3 ON t3.c = t1.c +ORDER BY a; +a b if(b = 1,i,if(b = 2,v,'')) +1 1 50 +2 1 25 +3 2 123 Park Place +4 2 453 Boardwalk +SELECT a,b,if(b = 1,i,if(b = 2,v,'')) +FROM t1 LEFT JOIN t2 ON t1.c = t2.c LEFT JOIN t3 ON t3.c = t1.c ORDER BY a; @@ -523,9 +542,15 @@ KEY `pseudo` (`pseudo`) ); INSERT INTO t1 (titre,auteur,dest) VALUES ('test','joce','bug'); INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug'); +SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; +titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest +test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug SELECT titre,numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug +SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; +titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest +test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug SELECT titre,numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index da5466a6e9d..16ead200933 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -519,16 +519,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -549,7 +549,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -591,7 +591,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -612,7 +612,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -654,7 +654,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -675,7 +675,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 237072d7218..9ab5a79f755 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -519,16 +519,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -549,7 +549,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -591,7 +591,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -612,7 +612,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -654,7 +654,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -675,7 +675,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 9b76003900a..8336a5bf99b 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -520,16 +520,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -550,7 +550,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -592,7 +592,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -613,7 +613,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -655,7 +655,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -676,7 +676,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index adb300fdcf1..f341247a417 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -562,16 +562,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -592,7 +592,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -634,7 +634,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -655,7 +655,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -697,7 +697,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -718,7 +718,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b @@ -3574,16 +3574,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -3604,7 +3604,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -3646,7 +3646,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -3667,7 +3667,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -3709,7 +3709,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -3730,7 +3730,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index d5a15fb4265..fe4536827e6 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -519,16 +519,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -549,7 +549,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -591,7 +591,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -612,7 +612,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -654,7 +654,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -675,7 +675,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 33769f400ae..c4cb92bdc02 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -519,16 +519,16 @@ a ? a drop table if exists t2 ; create table t2 as select * from t1 ; set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ; -set @query2= 'SELECT * FROM t2 natural join t1 order by a ' ; -set @query3= 'SELECT * FROM t2 join t1 using(a) order by a ' ; +set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ; +set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ; set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query5= 'SELECT * FROM t2 natural left join t1 order by a ' ; -set @query6= 'SELECT * FROM t2 left join t1 using(a) order by a ' ; +set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ; +set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ; set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ; -set @query8= 'SELECT * FROM t2 natural right join t1 order by a ' ; -set @query9= 'SELECT * FROM t2 right join t1 using(a) order by a ' ; +set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ; +set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ; the join statement is: -SELECT * FROM t2 right join t1 using(a) order by a +SELECT * FROM t2 right join t1 using(a) order by t2.a prepare stmt1 from @query9 ; execute stmt1 ; a b b @@ -549,7 +549,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural right join t1 order by a +SELECT * FROM t2 natural right join t1 order by t2.a prepare stmt1 from @query8 ; execute stmt1 ; a b @@ -591,7 +591,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 left join t1 using(a) order by a +SELECT * FROM t2 left join t1 using(a) order by t2.a prepare stmt1 from @query6 ; execute stmt1 ; a b b @@ -612,7 +612,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural left join t1 order by a +SELECT * FROM t2 natural left join t1 order by t2.a prepare stmt1 from @query5 ; execute stmt1 ; a b @@ -654,7 +654,7 @@ a b a b 3 three 3 three 4 four 4 four the join statement is: -SELECT * FROM t2 join t1 using(a) order by a +SELECT * FROM t2 join t1 using(a) order by t2.a prepare stmt1 from @query3 ; execute stmt1 ; a b b @@ -675,7 +675,7 @@ a b b 3 three three 4 four four the join statement is: -SELECT * FROM t2 natural join t1 order by a +SELECT * FROM t2 natural join t1 order by t2.a prepare stmt1 from @query2 ; execute stmt1 ; a b diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index b20949d4a62..6e28ecb5ec3 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -1350,6 +1350,20 @@ fld1 fld1 250504 250505 250505 250505 insert into t2 (fld1, companynr) values (999999,99); +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +companynr companyname +99 NULL +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +count(*) +1199 +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; companynr companyname select count(*) from t2 left join t4 using (companynr) where companynr is not null; @@ -1362,6 +1376,18 @@ explain select companynr,companyname from t4 left join t2 using (companynr) wher id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE delete from t2 where fld1=999999; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where @@ -1374,6 +1400,18 @@ explain select companynr,companyname from t4 left join t2 using (companynr) wher id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d3ab359702e..14806279362 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1789,10 +1789,18 @@ CREATE TABLE t1 (id INT); CREATE TABLE t2 (id INT); INSERT INTO t1 VALUES (1), (2); INSERT INTO t2 VALUES (1); +SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id); +id c +1 1 +2 0 SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id); id c 1 1 2 0 +SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY t1.id; +id c +1 1 +2 0 SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY id; id c 1 1 diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index 39c55206c60..1342603f755 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -307,17 +307,33 @@ create table t1 ( id integer unsigned not null primary key ); create table t2 ( id integer unsigned not null primary key ); insert into t1 values (1), (2); insert into t2 values (1); +select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); +id_A id_B +1 1 +2 NULL select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); id_A id_B 1 1 2 NULL create table t3 (id_A integer unsigned not null, id_B integer unsigned null ); +insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); +select * from t3; +id_A id_B +1 1 +2 NULL +delete from t3; insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; id_A id_B 1 1 2 NULL drop table t3; +create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); +select * from t3; +id_A id_B +1 1 +2 NULL +drop table t3; create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; id_A id_B diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 5e487bd8036..3167682f816 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -400,6 +400,7 @@ drop table t1; set @a:=now(); CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=bdb; insert into t1 (a) values(1),(2),(3); +select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a; select a from t1 natural join t1 as t2 where b >= @a order by a; update t1 set a=5 where a=1; select a from t1; @@ -571,7 +572,7 @@ create temporary table tmp1 select branch_id, target_id, platform_id, product_id from t1, t2, t3, t4 ; create temporary table tmp2 - select branch_id, target_id, platform_id, product_id + select tmp1.branch_id, tmp1.target_id, tmp1.platform_id, tmp1.product_id from tmp1 left join t8 using (branch_id,target_id,platform_id,product_id) where t8.archive_id is null ; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 3eaf408af0f..bf094dd0e5d 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -440,6 +440,7 @@ drop table t1; set @a:=now(); CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=innodb; insert into t1 (a) values(1),(2),(3); +select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a; select a from t1 natural join t1 as t2 where b >= @a order by a; update t1 set a=5 where a=1; select a from t1; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 2e82bad8abb..bb82a93c6c4 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -111,6 +111,10 @@ drop table t1, t2; create table t1 (a int primary key); insert into t1 values(1),(2); +select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a); +--replace_result "31 tables" "XX tables" "61 tables" "XX tables" +--error 1116 +select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a); select a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a); --replace_result "31 tables" "XX tables" "61 tables" "XX tables" --error 1116 @@ -144,6 +148,7 @@ DROP TABLE t1, t2; CREATE TABLE t1 (d DATE NOT NULL); CREATE TABLE t2 (d DATE NOT NULL); INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00'); +SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL; SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE d IS NULL; SELECT * from t1 WHERE t1.d IS NULL; SELECT * FROM t1 WHERE 1/0 IS NULL; @@ -266,6 +271,8 @@ CREATE TABLE t2 ( FULLTEXT KEY rate_code (rate_code) ) ENGINE=MyISAM; INSERT INTO t2 VALUES ('rivercats','cust',20); +SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats'; +SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND siteid = 'rivercats'; SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE siteid = 'rivercats' AND emp.emp_id = 'psmith'; drop table t1,t2; @@ -315,14 +322,14 @@ select * from t3 right join t2 on (t3.i=t2.i); select * from t3 natural right join t2 natural right join t1; select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i); -select * from t1,t2 natural left join t3 order by 1,2; +select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i; select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; -select * from t2 natural left join t3,t1 order by t1.i; +select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i; select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; -select * from t1,t2 natural right join t3 order by 1,2; +select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i; select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; -select * from t2 natural right join t3,t1 order by t1.i; +select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i; select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; drop table t1,t2,t3; diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test index f6b74237123..482c7f9f8b9 100644 --- a/mysql-test/t/join_nested.test +++ b/mysql-test/t/join_nested.test @@ -678,7 +678,7 @@ SELECT t2.a,t2.b,t3.a1,t3.b FROM t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL); -SELECT * +SELECT t2.a,t2.b,t3.a1,t3.b FROM t2 NATURAL LEFT JOIN t3 WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL); diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 6a3b79f8354..aabc32c009a 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -19,11 +19,11 @@ select t1.*,t2.* from t1 JOIN t2 where t1.a=t2.a; select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) order by t1.grp,t1.a,t2.c; select t1.*,t2.* from { oj t2 left outer join t1 on (t1.a=t2.a) }; select t1.*,t2.* from t1 as t0,{ oj t2 left outer join t1 on (t1.a=t2.a) } WHERE t0.a=2; -select * from t1 left join t2 using (a); -select t1.*,t2.* from t1 left join t2 on t1.a=t2.a; -select * from t1 left join t2 using (a,c); -select * from t1 left join t2 using (c); -select * from t1 natural left outer join t2; +select t1.*,t2.* from t1 left join t2 using (a); +select t1.*,t2.* from t1 left join t2 using (a) where t1.a=t2.a; +select t1.*,t2.* from t1 left join t2 using (a,c); +select t1.*,t2.* from t1 left join t2 using (c); +select t1.*,t2.* from t1 natural left outer join t2; select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) where t2.id=3; select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) where t2.id is null; @@ -44,9 +44,9 @@ select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a); # Test of inner join -select * from t1 inner join t2 using (a); +select t1.*,t2.* from t1 inner join t2 using (a); select t1.*,t2.* from t1 inner join t2 on (t1.a=t2.a); -select * from t1 natural join t2; +select t1.*,t2.* from t1 natural join t2; drop table t1,t2; @@ -325,7 +325,7 @@ INSERT INTO t2 VALUES (2,'y'); INSERT INTO t2 VALUES (3,'z'); SELECT t2.id2 FROM t2 LEFT OUTER JOIN t1 ON t1.id2 = t2.id2 WHERE id1 IS NULL; -SELECT id2 FROM t2 NATURAL LEFT OUTER JOIN t1 WHERE id1 IS NULL; +SELECT t2.id2 FROM t2 NATURAL LEFT OUTER JOIN t1 WHERE id1 IS NULL; drop table t1,t2; @@ -430,6 +430,8 @@ insert into t1 values(1),(2); insert into t2 values(2),(3); insert into t3 values(2),(4); select * from t1 natural left join t2 natural left join t3; +select * from t1 natural left join t2 where (t2.i is not null)=0; +select * from t1 natural left join t2 where (t2.i is not null) is not null; select * from t1 natural left join t2 where (i is not null)=0; select * from t1 natural left join t2 where (i is not null) is not null; drop table t1,t2,t3; @@ -656,6 +658,8 @@ create table t1 (a int, b varchar(20)); create table t2 (a int, c varchar(20)); insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb"); insert into t2 values (1,"cccccccccc"),(2,"dddddddddd"); +select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by t1.a; +select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a; select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a; select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a; drop table t1, t2; diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test index 4ab99fc5d6d..e15aec01d2a 100644 --- a/mysql-test/t/null_key.test +++ b/mysql-test/t/null_key.test @@ -152,18 +152,12 @@ INSERT INTO t1 (order_id, product_id, product_type) VALUES INSERT INTO t2 (order_id, product_id, product_type) VALUES ('9d9aad7764b5b2c53004348ef8d34500',2315652, 3); -select t1.* from t1 left join t2 - on (t1.order_id = t2.order_id and - t1.product_id = t2.product_id and - t1.product_type = t2.product_type) -where t2.order_id = NULL; - -select t1.* from t1 left join t2 - on (t1.order_id = t2.order_id and - t1.product_id = t2.product_id and - t1.product_type = t2.product_type) +select t1.* from t1 +left join t2 using(order_id, product_id, product_type) +where t2.order_id=NULL; +select t1.* from t1 +left join t2 using(order_id, product_id, product_type) where t2.order_id is NULL; - drop table t1,t2; # diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 615b317eb36..b1807579b20 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -151,11 +151,22 @@ INSERT INTO t2 VALUES (2,25); INSERT INTO t3 VALUES (1,'123 Park Place'); INSERT INTO t3 VALUES (2,'453 Boardwalk'); +SELECT a,b,if(b = 1,i,if(b = 2,v,'')) +FROM t1 +LEFT JOIN t2 USING(c) +LEFT JOIN t3 ON t3.c = t1.c; + SELECT a,b,if(b = 1,i,if(b = 2,v,'')) FROM t1 LEFT JOIN t2 ON t1.c = t2.c LEFT JOIN t3 ON t3.c = t1.c; +SELECT a,b,if(b = 1,i,if(b = 2,v,'')) +FROM t1 +LEFT JOIN t2 USING(c) +LEFT JOIN t3 ON t3.c = t1.c +ORDER BY a; + SELECT a,b,if(b = 1,i,if(b = 2,v,'')) FROM t1 LEFT JOIN t2 ON t1.c = t2.c @@ -339,7 +350,9 @@ CREATE TABLE t2 ( INSERT INTO t1 (titre,auteur,dest) VALUES ('test','joce','bug'); INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug'); +SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; SELECT titre,numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; +SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; SELECT titre,numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 8e74167852b..f580d3d1223 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1538,6 +1538,11 @@ select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 25 # insert into t2 (fld1, companynr) values (999999,99); +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; + select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; select count(*) from t2 left join t4 using (companynr) where companynr is not null; explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; @@ -1547,10 +1552,18 @@ delete from t2 where fld1=999999; # # Test left join optimization +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; + explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; # Following can't be optimized +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; + explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 22c5471dee2..5020902009d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1132,7 +1132,9 @@ CREATE TABLE t1 (id INT); CREATE TABLE t2 (id INT); INSERT INTO t1 VALUES (1), (2); INSERT INTO t2 VALUES (1); +SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id); SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id); +SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY t1.id; SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY id; DROP TABLE t1,t2; diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test index 85862821aab..03ee91f14d8 100644 --- a/mysql-test/t/type_ranges.test +++ b/mysql-test/t/type_ranges.test @@ -157,11 +157,18 @@ create table t1 ( id integer unsigned not null primary key ); create table t2 ( id integer unsigned not null primary key ); insert into t1 values (1), (2); insert into t2 values (1); +select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); create table t3 (id_A integer unsigned not null, id_B integer unsigned null ); +insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); +select * from t3; +delete from t3; insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; drop table t3; +create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); +select * from t3; +drop table t3; create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; drop table t1,t2,t3; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b8748b89fbd..8017a82f1ed 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2587,8 +2587,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, thd [in] thread handler table_ref [in] table reference to search name [in] name of field - table_name [in] optional table name that qualifies the field - db_name [in] optional database name that qualifies the field length [in] length of name ref [in/out] if 'name' is resolved to a view field, ref is set to point to the found view field @@ -2599,6 +2597,12 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, belongs - differs from 'table_list' only for NATURAL/USING joins + DESCRIPTION + Search for a field among the result fields of a NATURAL/USING join. + Notice that this procedure is called only for non-qualified field + names. In the case of qualified fields, we search directly the base + tables of a natural join. + RETURN NULL if the field was not found WRONG_GRANT if no access rights to the found field @@ -2607,7 +2611,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, static Field * find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, - const char *table_name, const char *db_name, uint length, Item **ref, bool check_grants, bool register_tree_change, TABLE_LIST **actual_table) @@ -2629,27 +2632,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, if (!(nj_col= field_it++)) DBUG_RETURN(NULL); - if (table_name) - { - /* - Coalesced columns cannot be qualified unless this is the execute phase - of prepared statements. The reason is that they do not belong to any - table, but for PS the prepare phase already resolves and stores - items, so during the execution phase we resolve fully qualified items. - */ - if (!thd->current_arena->is_stmt_execute() && nj_col->is_coalesced) - continue; - if (table_name[0] && - my_strcasecmp(table_alias_charset, nj_col->table_name(), table_name)) - continue; - if (db_name && db_name[0]) - { - const char *cur_db_name= nj_col->db_name(); - if (cur_db_name && strcmp(db_name, cur_db_name)) - continue; - } - } - if (!my_strcasecmp(system_charset_info, nj_col->name(), name)) break; } @@ -2842,11 +2824,35 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, *actual_table= table_list; } else if (table_list->is_natural_join) - fld= find_field_in_natural_join(thd, table_list, name, table_name, - db_name, length, ref, + { + if (table_name && table_name[0]) + { + /* + Qualified field; Search for it in the tables used by the natural join. + */ + List_iterator it(table_list->nested_join->join_list); + TABLE_LIST *table; + while ((table= it++)) + { + if ((fld= find_field_in_table_ref(thd, table, name, item_name, + table_name, db_name, length, ref, + check_grants_table, + check_grants_view, + allow_rowid, cached_field_index_ptr, + register_tree_change, actual_table))) + DBUG_RETURN(fld); + } + DBUG_RETURN(0); + } + /* + Non-qualified field, search directly in the result columns of the + natural join. + */ + fld= find_field_in_natural_join(thd, table_list, name, length, ref, /* TIMOUR_TODO: check this with Sanja */ check_grants_table || check_grants_view, register_tree_change, actual_table); + } else { if ((fld= find_field_in_table(thd, table_list->table, name, length, @@ -2915,9 +2921,11 @@ find_field_in_tables(THD *thd, Item_ident *item, const char *name= item->field_name; uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; - bool allow_rowid; TABLE_LIST *cur_table= first_table; TABLE_LIST *actual_table; + bool is_qualified= table_name && table_name[0]; + bool allow_rowid= is_qualified ? + TRUE : (cur_table && !cur_table->next_local); if (item->cached_table) { @@ -2988,81 +2996,13 @@ find_field_in_tables(THD *thd, Item_ident *item, if (last_table) last_table= last_table->next_name_resolution_table; - /* The field we search for is qualified with a table name and optional db. */ - if (table_name && table_name[0]) - { - for (; cur_table != last_table ; - cur_table= cur_table->next_name_resolution_table) - { - Field *cur_field= find_field_in_table_ref(thd, cur_table, name, - item->name, table_name, - db, length, ref, - (cur_table->table && - test(cur_table->table->grant. - want_privilege) && - check_privileges), - (test(cur_table->grant. - want_privilege) && - check_privileges), - 1, &(item->cached_field_index), - register_tree_change, - &actual_table); - if (cur_field) - { - /* - Store the original table of the field, which may be different from - cur_table in the case of NATURAL/USING join. - */ - item->cached_table= (!actual_table->cacheable_table) ? 0 : actual_table; - - if (cur_field == WRONG_GRANT) - return (Field*) 0; - if (db || !thd->where) - return cur_field; - if (found) - { - if (report_error == REPORT_ALL_ERRORS || - report_error == IGNORE_EXCEPT_NON_UNIQUE) - my_error(ER_NON_UNIQ_ERROR, MYF(0), - item->full_name(),thd->where); - return (Field*) 0; - } - found= cur_field; - } - } - if (found) - return found; - /* - If there were no tables to search, we wouldn't go through the loop and - cur_table wouldn't be updated by the loop increment part. - */ - if (cur_table == first_table && (report_error == REPORT_ALL_ERRORS || - report_error == REPORT_EXCEPT_NON_UNIQUE)) - { - char buff[NAME_LEN*2+1]; - if (db && db[0]) - { - strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); - table_name=buff; - } - my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where); - } - else - if (report_error == REPORT_ALL_ERRORS || - report_error == REPORT_EXCEPT_NON_UNIQUE) - my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(),thd->where); - else - return (Field*) not_found_field; - return (Field*) 0; - } - - /* The field we search for is not qualified. */ - allow_rowid= cur_table && !cur_table->next_local; for (; cur_table != last_table ; cur_table= cur_table->next_name_resolution_table) { Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name, - NULL, NULL, length, ref, + is_qualified ? table_name : NULL, + is_qualified ? db : NULL, + length, ref, (cur_table->table && test(cur_table->table->grant. want_privilege) && @@ -3086,26 +3026,57 @@ find_field_in_tables(THD *thd, Item_ident *item, item->cached_table= (!actual_table->cacheable_table || found) ? 0 : actual_table; + DBUG_ASSERT(thd->where); + /* + If we found a fully qualified field we return it directly as it can't + have duplicates. + */ + if (is_qualified && db) + return cur_field; + if (found) { - if (!thd->where) // Returns first found - break; if (report_error == REPORT_ALL_ERRORS || report_error == IGNORE_EXCEPT_NON_UNIQUE) - my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where); + my_error(ER_NON_UNIQ_ERROR, MYF(0), + is_qualified ? item->full_name() : name, thd->where); return (Field*) 0; } found= cur_field; } } + if (found) return found; - if (report_error == REPORT_ALL_ERRORS || - report_error == REPORT_EXCEPT_NON_UNIQUE) - my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where); + + /* + If the field was qualified and there were no tables to search, issue + an error that an unknown table was given. The situation is detected + as follows: if there were no tables we wouldn't go through the loop + and cur_table wouldn't be updated by the loop increment part, so it + will be equal to the first table. + */ + if (is_qualified && (cur_table == first_table) && + (report_error == REPORT_ALL_ERRORS || + report_error == REPORT_EXCEPT_NON_UNIQUE)) + { + char buff[NAME_LEN*2+1]; + if (db && db[0]) + { + strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); + table_name=buff; + } + my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where); + } else - return (Field*) not_found_field; - return (Field*) 0; + if (report_error == REPORT_ALL_ERRORS || + report_error == REPORT_EXCEPT_NON_UNIQUE) + my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where); + else + found= not_found_field; + + DBUG_ASSERT(!found || found == not_found_field); + return found; } @@ -3510,10 +3481,6 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, Item_ident *item_ident_1, *item_ident_2; Item_func_eq *eq_cond; - DBUG_PRINT("info", ("new equi-join condition: %s.%s = %s.%s", - table_ref_1->alias, field_1->field_name, - table_ref_2->alias, field_2->field_name)); - if (!item_1 || !item_2) goto err; // out of memory @@ -3560,7 +3527,6 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, eq_cond); nj_col_1->is_common= nj_col_2->is_common= TRUE; - nj_col_1->is_coalesced= nj_col_2->is_coalesced= TRUE; if (field_1) { @@ -4310,29 +4276,28 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, } found= FALSE; - for (TABLE_LIST *tables= context->first_name_resolution_table; + + /* + If table names are qualified, then loop over all tables used in the query, + else treat natural joins as leaves and do not iterate over their underlying + tables. + */ + for (TABLE_LIST *tables= (table_name ? context->table_list : + context->first_name_resolution_table); tables; - tables= tables->next_name_resolution_table) + tables= (table_name ? tables->next_local : + tables->next_name_resolution_table) + ) { Field *field; TABLE *table= tables->table; DBUG_ASSERT(tables->is_leaf_for_name_resolution()); - /* - If optional table and db names do not match the ones used to qualify - the field being expanded, skip this table reference. However if this is - a NATURAL/USING join, we can't simply skip the whole table reference, - because its columns may come from different tables/views. For NATURAL/ - USING joins we perform this test for each column in the loop below. - */ - if (!tables->is_natural_join) - { - if (table_name && my_strcasecmp(table_alias_charset, table_name, - tables->alias) || - (db_name && strcmp(tables->db,db_name))) - continue; - } + if (table_name && my_strcasecmp(table_alias_charset, table_name, + tables->alias) || + (db_name && strcmp(tables->db,db_name))) + continue; #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access rights to all fields to be inserted. */ @@ -4369,21 +4334,6 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, { Item *item; - /* - If this is a column of a NATURAL/USING join, and the star was - qualified with a table (and database) name, check if the - column is not a coalesced one, and if not, that is belongs to - the same table. - */ - if (tables->is_natural_join && table_name) - { - if (field_iterator.is_coalesced() || - my_strcasecmp(table_alias_charset, table_name, - field_iterator.table_name()) || - (db_name && strcmp(db_name, field_iterator.db_name()))) - continue; - } - if (!(item= field_iterator.create_item(thd))) DBUG_RETURN(TRUE); @@ -4410,18 +4360,18 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, tables->is_natural_join); DBUG_ASSERT(item->type() == Item::FIELD_ITEM); Item_field *fld= (Item_field*) item; - const char *table_name= field_iterator.table_name(); + const char *field_table_name= field_iterator.table_name(); if (!tables->schema_table && !(fld->have_privileges= (get_column_grant(thd, field_iterator.grant(), field_iterator.db_name(), - table_name, fld->field_name) & + field_table_name, fld->field_name) & VIEW_ANY_ACL))) { my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY", thd->priv_user, thd->host_or_ip, - fld->field_name, table_name); + fld->field_name, field_table_name); DBUG_RETURN(TRUE); } } diff --git a/sql/table.cc b/sql/table.cc index beecd6442e8..5983b9afda7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2289,7 +2289,6 @@ Natural_join_column::Natural_join_column(Field_translator *field_param, table_field= NULL; table_ref= tab; is_common= FALSE; - is_coalesced= FALSE; } @@ -2301,7 +2300,6 @@ Natural_join_column::Natural_join_column(Field *field_param, view_field= NULL; table_ref= tab; is_common= FALSE; - is_coalesced= FALSE; } @@ -2641,13 +2639,6 @@ GRANT_INFO *Field_iterator_table_ref::grant() } -bool Field_iterator_table_ref::is_coalesced() -{ - if (table_ref->is_natural_join) - return natural_join_it.column_ref()->is_coalesced; - return FALSE; -} - /* Create new or return existing column reference to a column of a natural/using join. diff --git a/sql/table.h b/sql/table.h index c0e4ad4c150..b6616150610 100644 --- a/sql/table.h +++ b/sql/table.h @@ -388,12 +388,6 @@ public: we are looking at some column. */ bool is_common; - /* - A column is coalesced if it was common in some of several nested NATURAL/ - USING joins. We have to know this, because according to ANSI, coalesced - columns cannot be qualified. - */ - bool is_coalesced; public: Natural_join_column(Field_translator *field_param, st_table_list *tab); Natural_join_column(Field *field_param, st_table_list *tab); @@ -741,7 +735,6 @@ public: const char *table_name(); const char *db_name(); GRANT_INFO *grant(); - bool is_coalesced(); Item *create_item(THD *thd) { return field_it->create_item(thd); } Field *field() { return field_it->field(); } Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 5558028bb06..75b41ebe4d1 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11801,8 +11801,8 @@ static void test_bug6046() stmt= mysql_stmt_init(mysql); - stmt_text= "SELECT a FROM t1 NATURAL JOIN t1 as X1 " - "WHERE b > ? ORDER BY a"; + stmt_text= "SELECT t1.a FROM t1 NATURAL JOIN t1 as X1 " + "WHERE t1.b > ? ORDER BY t1.a"; rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); check_execute(stmt, rc); From 142f65834b73e99cce98d9c537c22584bdd81033 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 19:00:28 +0300 Subject: [PATCH 49/80] Test case for BUG#10972 - Natural join of view and underlying table gives wrong result. The bug itself is fixed by WL#2486. mysql-test/r/select.result: Test case for BUG#10972. mysql-test/t/select.test: Test case for BUG#10972. --- mysql-test/r/select.result | 11 +++++++++++ mysql-test/t/select.test | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 801af85da64..1fb460535ef 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2818,3 +2818,14 @@ create table t2 (pk int primary key, c int); select pk from t1 inner join t2 using (pk); pk drop table t1,t2; +create table t1 (s1 int, s2 char(5), s3 decimal(10)); +create view v1 as select s1, s2, 'x' as s3 from t1; +select * from t1 natural join v1; +s1 s2 s3 +insert into t1 values (1,'x',5); +select * from t1 natural join v1; +s1 s2 s3 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +drop table t1; +drop view v1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 61f792a799f..250d1972bf7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2394,3 +2394,15 @@ create table t1 (pk int primary key, b int); create table t2 (pk int primary key, c int); select pk from t1 inner join t2 using (pk); drop table t1,t2; + +# +# Bug #10972 Natural join of view and underlying table gives wrong result +# + +create table t1 (s1 int, s2 char(5), s3 decimal(10)); +create view v1 as select s1, s2, 'x' as s3 from t1; +select * from t1 natural join v1; +insert into t1 values (1,'x',5); +select * from t1 natural join v1; +drop table t1; +drop view v1; From b4e830c3e33cc229fef3e037bf44dbfc5109d731 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 20:03:32 +0300 Subject: [PATCH 50/80] Fix for BUG#6276. mysql-test/r/select.result: Test for BUG#6276. mysql-test/t/select.test: Test for BUG#6276. sql/sql_base.cc: Add a true ON condition for outer joins without common columns. --- mysql-test/r/select.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/select.test | 20 ++++++++++++++++++++ sql/sql_base.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1fb460535ef..8d52dcc22fe 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2829,3 +2829,34 @@ Warnings: Warning 1292 Truncated incorrect DOUBLE value: 'x' drop table t1; drop view v1; +create table t1(a1 int); +create table t2(a2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create view v2 (c) as select a1 from t1; +select * from t1 natural left join t2; +a1 a2 +1 1 +1 2 +2 1 +2 2 +select * from t1 natural right join t2; +a2 a1 +1 1 +1 2 +2 1 +2 2 +select * from v2 natural left join t2; +c a2 +1 1 +1 2 +2 1 +2 2 +select * from v2 natural right join t2; +a2 c +1 1 +1 2 +2 1 +2 2 +drop table t1, t2; +drop view v2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 250d1972bf7..414af3f9131 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2406,3 +2406,23 @@ insert into t1 values (1,'x',5); select * from t1 natural join v1; drop table t1; drop view v1; + +# +# Bug #6276 A SELECT that does a NATURAL OUTER JOIN without common +# columns crashes server because of empty ON condition +# + +create table t1(a1 int); +create table t2(a2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(2); +create view v2 (c) as select a1 from t1; + +select * from t1 natural left join t2; +select * from t1 natural right join t2; + +select * from v2 natural left join t2; +select * from v2 natural right join t2; + +drop table t1, t2; +drop view v2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 763fbc6c336..a7f5fa3ce03 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3851,6 +3851,11 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, */ table_ref_1->natural_join= table_ref_2->natural_join= NULL; + /* Add a TRUE condition to outer joins that have no common columns. */ + if (table_ref_2->outer_join && + !table_ref_1->on_expr && !table_ref_2->on_expr) + table_ref_2->on_expr= new Item_int((longlong) 1,1); /* Always true. */ + /* Change this table reference to become a leaf for name resolution. */ if (left_neighbor) { From 6401b90ddf9944af222b0dd1d5d9b11f17af0f48 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 19:16:43 +0200 Subject: [PATCH 51/80] Add the "test-force" target to "Makefile.am". Makefile.am: Add the "test-force" target, because we use it in RPM building. (Backport of Monty's fix from 5.0) --- Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 96f3561e31c..5900d709dcf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,4 +100,10 @@ tags: # Test installation test: - cd mysql-test; perl mysql-test-run.pl && perl mysql-test-run.pl --ps-protocol + cd mysql-test; \ + perl ./mysql-test-run && perl ./mysql-test-run --ps-protocol + +test-force: + cd mysql-test; \ + ./mysql-test-run --force ;\ + ./mysql-test-run --ps-protocol --force From 4bf5c7c55b2033d3e8b218472550c35e2cda07f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 20:24:29 +0300 Subject: [PATCH 52/80] Test for BUG#4889 - inconsistent resilts of more than 2-way natural join due to incorrect transformation to JOIN ... ON. The bug itself is fixed by WL#2486. mysql-test/r/select.result: Test for BUG#4889. mysql-test/t/select.test: Test for BUG#4889. --- mysql-test/r/select.result | 15 +++++++++++++++ mysql-test/t/select.test | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 8d52dcc22fe..47dbdd49db9 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2860,3 +2860,18 @@ a2 c 2 2 drop table t1, t2; drop view v2; +create table t1 (a int(10), t1_val int(10)); +create table t2 (b int(10), t2_val int(10)); +create table t3 (a int(10), b int(10)); +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(2,2),(3,3); +insert into t3 values (1,1),(2,1),(3,1),(4,1); +select * from t1 natural join t2 natural join t3; +a b t1_val t2_val +1 1 1 1 +2 1 2 1 +select * from t1 natural join t3 natural join t2; +b a t1_val t2_val +1 1 1 1 +1 2 2 1 +drop table t1, t2, t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 414af3f9131..21fc4c25e61 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2426,3 +2426,20 @@ select * from v2 natural right join t2; drop table t1, t2; drop view v2; + + +# +# Bug #4789 Incosistent results of more than 2-way natural joins due to +# incorrect transformation to join ... on. +# + +create table t1 (a int(10), t1_val int(10)); +create table t2 (b int(10), t2_val int(10)); +create table t3 (a int(10), b int(10)); +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(2,2),(3,3); +insert into t3 values (1,1),(2,1),(3,1),(4,1); +# the following two queries must return the same result +select * from t1 natural join t2 natural join t3; +select * from t1 natural join t3 natural join t2; +drop table t1, t2, t3; From 4b9431369611b4c3938288c0ef9eaa282f1bb417 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 11:25:24 -0700 Subject: [PATCH 53/80] Fix build using --without-server. (Bug #11680) configure.in: Fix directories built using --without-server, and add mf_keycache.o to list of objects only built for thread-safe library, since it requires threading. dbug/my_main.c: Don't try to initialize thread globals if not built with threading. mysys/Makefile.am: Remove mf_keycache.c from list of files to build (it will be included in THREAD_LOBJECTS when appropriate). mysys/mf_getdate.c: Fix usage of gmtime(). sql/share/Makefile.am: Allow removal of mysqld_error.h to fail, in case it doesn't exist yet. tests/Makefile.am: Don't link against libmysys explicitly. --- configure.in | 7 +++---- dbug/my_main.c | 2 ++ mysys/Makefile.am | 2 +- mysys/mf_getdate.c | 2 +- sql/share/Makefile.am | 2 +- tests/Makefile.am | 3 +-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/configure.in b/configure.in index 8a5220dbf38..612a51586ab 100644 --- a/configure.in +++ b/configure.in @@ -2444,7 +2444,7 @@ thread_dirs= dnl This probably should be cleaned up more - for now the threaded dnl client is just using plain-old libs. -sql_client_dirs="libmysql strings regex client" +sql_client_dirs="strings regex mysys sql/share libmysql client" linked_client_targets="linked_libmysql_sources" if test "$THREAD_SAFE_CLIENT" != "no" @@ -2482,10 +2482,10 @@ then AC_DEFINE([THREAD], [1], [Define if you want to have threaded code. This may be undef on client code]) # Avoid _PROGRAMS names - THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o" + THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o" AC_SUBST(THREAD_LOBJECTS) server_scripts="mysqld_safe mysql_install_db" - sql_server_dirs="strings mysys dbug extra regex" + sql_server_dirs="strings dbug extra regex" # @@ -2593,7 +2593,6 @@ esac # END of configuration for optional table handlers # sql_server_dirs="$sql_server_dirs myisam myisammrg heap vio sql" - fi # IMPORTANT - do not modify LIBS past this line - this hack is the only way diff --git a/dbug/my_main.c b/dbug/my_main.c index 90af23b42b9..ed1c9329235 100644 --- a/dbug/my_main.c +++ b/dbug/my_main.c @@ -18,7 +18,9 @@ char *argv[]; #if defined(HAVE_PTHREAD_INIT) && defined(THREAD) pthread_init(); /* Must be called before DBUG_ENTER */ #endif +#ifdef THREAD my_thread_global_init(); +#endif { DBUG_ENTER ("main"); DBUG_PROCESS (argv[0]); diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 9c58c18cf59..868f68096ae 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -30,7 +30,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \ my_pread.c my_write.c \ - mf_keycache.c mf_keycaches.c my_crc32.c \ + mf_keycaches.c my_crc32.c \ mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c index b12e68cc1f9..8998da8aefa 100644 --- a/mysys/mf_getdate.c +++ b/mysys/mf_getdate.c @@ -54,7 +54,7 @@ void get_date(register my_string to, int flag, time_t date) if (flag & GETDATE_GMT) start_time= localtime(&skr); else - gmtime(&skr,&tm_tmp); + start_time= gmtime(&skr); #endif if (flag & GETDATE_SHORT_DATE) sprintf(to,"%02d%02d%02d", diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index b7ab8fead22..2e23027f1f5 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -33,7 +33,7 @@ all-local: english/errmsg.sys # created. Normally these are created by extra/Makefile english/errmsg.sys: errmsg.txt - rm $(top_builddir)/include/mysqld_error.h + rm -f $(top_builddir)/include/mysqld_error.h (cd $(top_builddir)/extra && $(MAKE)) install-data-local: diff --git a/tests/Makefile.am b/tests/Makefile.am index ca7f04c91f9..131f8b1b625 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,8 +42,7 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la -mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) \ - $(top_builddir)/mysys/libmysys.a +mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix) select_test_SOURCES= select_test.c $(yassl_dummy_link_fix) From 96f884c03a1d85ec550d15157f99ab70dd7cf19f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Aug 2005 22:29:05 +0300 Subject: [PATCH 54/80] Test for BUG#6495. The bug itself is fixed by WL#2486. mysql-test/r/select.result: Test for BUG#6495. mysql-test/t/select.test: Test for BUG#6495. --- mysql-test/r/select.result | 12 ++++++++++++ mysql-test/t/select.test | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 47dbdd49db9..83682d87504 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2875,3 +2875,15 @@ b a t1_val t2_val 1 1 1 1 1 2 2 1 drop table t1, t2, t3; +create table t1 (a char(1)); +create table t2 (a char(1)); +insert into t1 values ('a'),('b'),('c'); +insert into t2 values ('b'),('c'),('d'); +select a from t1 natural join t2; +a +b +c +select * from t1 natural join t2 where a = 'b'; +a +b +drop table t1, t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 21fc4c25e61..ebd382b1df1 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2443,3 +2443,16 @@ insert into t3 values (1,1),(2,1),(3,1),(4,1); select * from t1 natural join t2 natural join t3; select * from t1 natural join t3 natural join t2; drop table t1, t2, t3; + + +# +# Bug #6495 Illogical requirement for column qualification in NATURAL join +# + +create table t1 (a char(1)); +create table t2 (a char(1)); +insert into t1 values ('a'),('b'),('c'); +insert into t2 values ('b'),('c'),('d'); +select a from t1 natural join t2; +select * from t1 natural join t2 where a = 'b'; +drop table t1, t2; From 15f626c2931097029b94f7361d88441fe691820d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 01:45:15 +0200 Subject: [PATCH 55/80] BUG#12532: Fixes after review sql/log_event.cc: Review fixes sql/sql_parse.cc: Review fixes --- sql/log_event.cc | 13 ++++++------- sql/sql_parse.cc | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index a07efc21915..9e8c0695b90 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1330,14 +1330,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + time_zone_len + 1 + - data_len + 1 + -#ifndef MYSQL_CLIENT -#ifdef HAVE_QUERY_CACHE - QUERY_CACHE_FLAGS_SIZE + + data_len + 1 +#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE) + + QUERY_CACHE_FLAGS_SIZE + + db_len + 1 #endif -#endif - db_len + 1, MYF(MY_WME)))) - DBUG_VOID_RETURN; + , MYF(MY_WME)))) + DBUG_VOID_RETURN; if (catalog_len) // If catalog is given { if (likely(catalog_nz)) // true except if event comes from 5.0.0|1|2|3. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 31d0f3eb675..70920b07a97 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1218,7 +1218,8 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) length--; buff[length]=0; thd->query_length=length; - thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1); + thd->query= thd->memdup_w_gap(buff, length+1, + thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); thd->query[length] = '\0'; /* We don't need to obtain LOCK_thread_count here because in bootstrap From 78c948830bcccdf21b459b4944d12331aaaf5d12 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 02:46:13 +0200 Subject: [PATCH 56/80] fix compilation failure appeared after monty's cleanup sql/sp_head.cc: fix #ifndef ... #endif to include block completely --- sql/sp_head.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index ebcbfb67fc8..dfc91f5a3f4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -227,8 +227,8 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val))); -#endif } +#endif break; } case STRING_RESULT: From 2f044d3d93a5c87032a39402c35abe460c6773f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 10:51:28 +0300 Subject: [PATCH 57/80] Post-fix for BUG#6276. sql/sql_base.cc: Fixed a bug in PS (prepared statements) mode - the "always TRUE" constant Item created for outer joins with no common columns was not created in the PS memory. Now it is created in the right memory. --- sql/sql_base.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a7f5fa3ce03..b2ed392d1ac 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3763,8 +3763,13 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, TABLE_LIST *left_neighbor, TABLE_LIST *right_neighbor) { + Query_arena *arena, backup; + bool result= TRUE; + DBUG_ENTER("store_top_level_join_columns"); + arena= thd->change_arena_if_needed(&backup); + /* Call the procedure recursively for each nested table reference. */ if (table_ref->nested_join) { @@ -3797,7 +3802,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, if (cur_table_ref->nested_join && store_top_level_join_columns(thd, cur_table_ref, cur_left_neighbor, cur_right_neighbor)) - DBUG_RETURN(TRUE); + goto err; cur_right_neighbor= cur_table_ref; } } @@ -3829,7 +3834,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, swap_variables(TABLE_LIST*, table_ref_1, table_ref_2); if (mark_common_columns(thd, table_ref_1, table_ref_2, using_fields, &found_using_fields)) - DBUG_RETURN(TRUE); + goto err; /* Swap the join operands back, so that we pick the columns of the second @@ -3841,7 +3846,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, if (store_natural_using_join_columns(thd, table_ref, table_ref_1, table_ref_2, using_fields, found_using_fields)) - DBUG_RETURN(TRUE); + goto err; /* Change NATURAL JOIN to JOIN ... ON. We do this for both operands @@ -3872,7 +3877,12 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, else table_ref->next_name_resolution_table= NULL; } - DBUG_RETURN(FALSE); + result= FALSE; /* All is OK. */ + +err: + if (arena) + thd->restore_backup_item_arena(arena, &backup); + DBUG_RETURN(result); } From 0183ec75e18c5725300a61afd92f93396d56acef Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 12:25:57 +0400 Subject: [PATCH 58/80] fix test for a bug to use correct tables mysql-test/r/sp.result: fix result mysql-test/t/sp.test: fix test for a bug: tests in sp.test should reuse tables t1 and t2 and create/drop tables t3, t4 etc. So, tables t1 and t2 were renamed into t3 and t4 --- mysql-test/r/sp.result | 33 +++++++++++++++++---------------- mysql-test/t/sp.test | 33 +++++++++++++++++---------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d1d41035475..423cd546a84 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3101,16 +3101,16 @@ call p_bug11247(10)| drop function f_bug11247| drop procedure p_bug11247| drop procedure if exists bug12168| -drop table if exists t1, t2| -create table t1 (a int)| -insert into t1 values (1),(2),(3),(4)| -create table t2 (a int)| +drop table if exists t3, t4| +create table t3 (a int)| +insert into t3 values (1),(2),(3),(4)| +create table t4 (a int)| create procedure bug12168(arg1 char(1)) begin declare b, c integer; if arg1 = 'a' then begin -declare c1 cursor for select a from t1 where a % 2; +declare c1 cursor for select a from t3 where a % 2; declare continue handler for not found set b = 1; set b = 0; open c1; @@ -3119,14 +3119,14 @@ fetch c1 into c; if (b = 1) then leave c1_repeat; end if; -insert into t2 values (c); +insert into t4 values (c); until b = 1 end repeat; end; end if; if arg1 = 'b' then begin -declare c2 cursor for select a from t1 where not a % 2; +declare c2 cursor for select a from t3 where not a % 2; declare continue handler for not found set b = 1; set b = 0; open c2; @@ -3135,35 +3135,36 @@ fetch c2 into c; if (b = 1) then leave c2_repeat; end if; -insert into t2 values (c); +insert into t4 values (c); until b = 1 end repeat; end; end if; end| call bug12168('a')| -select * from t2| +select * from t4| a 1 3 -truncate t2| +truncate t4| call bug12168('b')| -select * from t2| +select * from t4| a 2 4 -truncate t2| +truncate t4| call bug12168('a')| -select * from t2| +select * from t4| a 1 3 -truncate t2| +truncate t4| call bug12168('b')| -select * from t2| +select * from t4| a 2 4 -truncate t2| +truncate t4| +drop table t3, t4| drop procedure if exists bug12168| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f3e7c3e07a0..abff597405b 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3934,20 +3934,20 @@ drop procedure p_bug11247| # --disable_warnings drop procedure if exists bug12168| -drop table if exists t1, t2| +drop table if exists t3, t4| --enable_warnings -create table t1 (a int)| -insert into t1 values (1),(2),(3),(4)| +create table t3 (a int)| +insert into t3 values (1),(2),(3),(4)| -create table t2 (a int)| +create table t4 (a int)| create procedure bug12168(arg1 char(1)) begin declare b, c integer; if arg1 = 'a' then begin - declare c1 cursor for select a from t1 where a % 2; + declare c1 cursor for select a from t3 where a % 2; declare continue handler for not found set b = 1; set b = 0; open c1; @@ -3957,14 +3957,14 @@ begin leave c1_repeat; end if; - insert into t2 values (c); + insert into t4 values (c); until b = 1 end repeat; end; end if; if arg1 = 'b' then begin - declare c2 cursor for select a from t1 where not a % 2; + declare c2 cursor for select a from t3 where not a % 2; declare continue handler for not found set b = 1; set b = 0; open c2; @@ -3974,7 +3974,7 @@ begin leave c2_repeat; end if; - insert into t2 values (c); + insert into t4 values (c); until b = 1 end repeat; end; @@ -3982,17 +3982,18 @@ begin end| call bug12168('a')| -select * from t2| -truncate t2| +select * from t4| +truncate t4| call bug12168('b')| -select * from t2| -truncate t2| +select * from t4| +truncate t4| call bug12168('a')| -select * from t2| -truncate t2| +select * from t4| +truncate t4| call bug12168('b')| -select * from t2| -truncate t2| +select * from t4| +truncate t4| +drop table t3, t4| drop procedure if exists bug12168| # From 43e07c3b916bb967838c2dc5c63be3589385b4cf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 11:14:41 +0200 Subject: [PATCH 59/80] BUG#12532: Fix for the case when my_malloc is macro sql/log_event.cc: my_malloc can be a macro --- sql/log_event.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 9e8c0695b90..c0a06bf5dab 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1328,14 +1328,19 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } } +#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE) if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + time_zone_len + 1 + - data_len + 1 -#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE) - + QUERY_CACHE_FLAGS_SIZE + - db_len + 1 + data_len + 1 + + QUERY_CACHE_FLAGS_SIZE + + db_len + 1, + MYF(MY_WME)))) +#else + if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + + time_zone_len + 1 + + data_len + 1, + MYF(MY_WME)))) #endif - , MYF(MY_WME)))) DBUG_VOID_RETURN; if (catalog_len) // If catalog is given { From a57d2444580dde5dbb19f7f3675cd6bf4e577370 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 12:51:00 +0200 Subject: [PATCH 60/80] Fix for bug#5501 (SHOW TABLE STATUS should show "view" in upper case) mysql-test/r/information_schema.result: changed output "view" to uppercase mysql-test/r/view.result: changed output "view" to uppercase sql/sql_show.cc: changed table field "view" to uppercase --- mysql-test/r/information_schema.result | 2 +- mysql-test/r/view.result | 12 ++++++------ sql/sql_show.cc | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 404a20d5e9e..029e06ed1ba 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -152,7 +152,7 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL t3 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL t5 MyISAM 10 Fixed 1 7 7 # 2048 0 11 # # NULL latin1_swedish_ci NULL -v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view +v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW show full columns from t3 like "a%"; Field Type Collation Null Key Default Extra Privileges Comment a int(11) NULL YES MUL NULL select,insert,update,references diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f56c6558e4f..6467c080a17 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -150,12 +150,12 @@ 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 10 Fixed 5 9 45 # 1024 0 NULL # # NULL latin1_swedish_ci NULL -v1 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 view -v3 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view -v4 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view -v5 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view -v6 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view +v1 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 VIEW +v3 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW +v4 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW +v5 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW +v6 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW drop view v1,v2,v3,v4,v5,v6; create view v1 (c,d,e,f) as select a,b, a in (select a+2 from t1), a = all (select a from t1) from t1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d1a968d2376..4a2315582fb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2210,7 +2210,7 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, else if (tables->view) { table->field[3]->store("VIEW", 4, cs); - table->field[20]->store("view", 4, cs); + table->field[20]->store("VIEW", 4, cs); } else { From b5c80bdba102f86bf723c89b08270d8aa2cf0643 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 13:41:34 +0200 Subject: [PATCH 61/80] Increase version number (but leave status still at "beta"). --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 4aef78e5b18..5b3cfad6105 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.12-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.13-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,7 +18,7 @@ SHARED_LIB_VERSION=15:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=12 +NDB_VERSION_BUILD=13 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From 4c76d94f2e0c3715ec4436ee77001370522c6ba6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 17:27:46 +0300 Subject: [PATCH 62/80] ha_innodb.cc: Fix bug #12779 : never give a row count estimate of 0 to the MySQL query optimizer, as then left join optimizer may beleive it KNOWS that the table is empty; note that this fix may change query optimization of many other queries where one table is empty; note that the proper fix would be to make the query optimizer to know that the row count estimates it receives really are just estimates, it cannot assume they are certain sql/ha_innodb.cc: Fix bug #12779 : never give a row count estimate of 0 to the MySQL query optimizer, as then left join optimizer may beleive it KNOWS that the table is empty; note that this fix may change query optimization of many other queries where one table is empty; note that the proper fix would be to make the query optimizer to know that the row count estimates it receives really are just estimates, it cannot assume they are certain --- sql/ha_innodb.cc | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index bcd07198f5c..3ae56f13478 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4109,6 +4109,7 @@ ha_innobase::info( dict_table_t* ib_table; dict_index_t* index; ha_rows rec_per_key; + ib_longlong n_rows; ulong j; ulong i; @@ -4151,7 +4152,30 @@ ha_innobase::info( } if (flag & HA_STATUS_VARIABLE) { - records = (ha_rows)ib_table->stat_n_rows; + n_rows = ib_table->stat_n_rows; + + /* Because we do not protect stat_n_rows by any mutex in a + delete, it is theoretically possible that the value can be + smaller than zero! TODO: fix this race. + + The MySQL optimizer seems to assume in a left join that n_rows + is an accurate estimate if it is zero. Of course, it is not, + since we do not have any locks on the rows yet at this phase. + Since SHOW TABLE STATUS seems to call this function with the + HA_STATUS_TIME flag set, while the left join optizer does not + set that flag, we add one to a zero value if the flag is not + set. That way SHOW TABLE STATUS will show the best estimate, + while the optimizer never sees the table empty. */ + + if (n_rows < 0) { + n_rows = 0; + } + + if (n_rows == 0 && !(flag & HA_STATUS_TIME)) { + n_rows++; + } + + records = (ha_rows)n_rows; deleted = 0; data_file_length = ((ulonglong) ib_table->stat_clustered_index_size) From 7e03ff1e595736ff2a82b6b58c47ad217e8bada8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 18:05:54 +0300 Subject: [PATCH 63/80] subselect2.result: Update test result to reflect the fix of Bug #12779 : EXPLAIN SELECT of a subquery is now different mysql-test/r/subselect2.result: Update test result to reflect the fix of Bug #12779 : EXPLAIN SELECT of a subquery is now different --- mysql-test/r/subselect2.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index b04fec26c6f..148c670c589 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -120,9 +120,9 @@ DOCID DOCNAME DOCTYPEID FOLDERID AUTHOR CREATED TITLE SUBTITLE DOCABSTRACT PUBLI c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff17444553544200 c373e9f5ad0796c0eca4444553544200 Goldilocks 2003-06-09 11:21:06 Title: Last Discussion NULL Setting new abstract and keeping doc checked out 2003-06-09 10:51:26 2003-06-09 10:51:26 NULL NULL NULL 03eea05112b845949f3fd03278b5fe43 2003-06-09 11:21:06 admin 0 NULL Discussion NULL NULL EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion'; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system PRIMARY NULL NULL NULL 0 const row not found 1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 9 Using where 1 PRIMARY t4 eq_ref PRIMARY PRIMARY 32 test.t2.DOCTYPEID 1 +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1 2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where From 7b39b01b9a7d607e19212812a5b718357c08ff04 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 19:37:27 +0300 Subject: [PATCH 64/80] Review fixes mysql-test/r/ctype_cp932.result: Remove first event to make things portable mysql-test/r/rpl_drop_db.result: Use 'mysqltest' as database instead of 'd1' Made test faster by using longer table names instead of lots of tables mysql-test/t/ctype_cp932.test: Remove first event to make things portable mysql-test/t/rpl_drop_db.test: Use 'mysqltest' as database instead of 'd1' Made test faster by using longer table names instead of lots of tables sql/sql_db.cc: Indentation & style fixes Simple optimization (remove constant and boolean variable) --- mysql-test/r/ctype_cp932.result | 3 +- mysql-test/r/rpl_drop_db.result | 1034 +------------------------------ mysql-test/t/ctype_cp932.test | 2 +- mysql-test/t/rpl_drop_db.test | 34 +- sql/sql_db.cc | 94 ++- 5 files changed, 84 insertions(+), 1083 deletions(-) diff --git a/mysql-test/r/ctype_cp932.result b/mysql-test/r/ctype_cp932.result index 0711f251a07..d8221a58b9e 100644 --- a/mysql-test/r/ctype_cp932.result +++ b/mysql-test/r/ctype_cp932.result @@ -8581,9 +8581,8 @@ CREATE TABLE t1(f1 blob); PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; SET @var1= x'8300'; EXECUTE stmt1 USING @var1; -SHOW BINLOG EVENTS; +SHOW BINLOG EVENTS FROM 79; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000001 # Start 1 # Server ver: 4.1.15-debug-log, Binlog ver: 3 master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8 master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(f1 blob) master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8 diff --git a/mysql-test/r/rpl_drop_db.result b/mysql-test/r/rpl_drop_db.result index 01a2af5341b..3d1dfba5b05 100644 --- a/mysql-test/r/rpl_drop_db.result +++ b/mysql-test/r/rpl_drop_db.result @@ -4,1029 +4,29 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -drop database if exists d1; -create database d1; -create table d1.t1 (n int); -insert into d1.t1 values (1); -select * from d1.t1 into outfile 'd1/f1.txt'; -create table d1.t2 (n int); -create table d1.t3 (n int); -drop database d1; -ERROR HY000: Error dropping database (can't rmdir './d1/', errno: 17) -use d1; +drop database if exists mysqltest; +create database mysqltest; +create table mysqltest.t1 (n int); +insert into mysqltest.t1 values (1); +select * from mysqltest.t1 into outfile 'mysqltest/f1.txt'; +create table mysqltest.t2 (n int); +create table mysqltest.t3 (n int); +drop database mysqltest; +ERROR HY000: Error dropping database (can't rmdir './mysqltest/', errno: 17) +use mysqltest; show tables; -Tables_in_d1 -create table d1.t1000(n int); -create table d1.t999(n int); -create table d1.t998(n int); -create table d1.t997(n int); -create table d1.t996(n int); -create table d1.t995(n int); -create table d1.t994(n int); -create table d1.t993(n int); -create table d1.t992(n int); -create table d1.t991(n int); -create table d1.t990(n int); -create table d1.t989(n int); -create table d1.t988(n int); -create table d1.t987(n int); -create table d1.t986(n int); -create table d1.t985(n int); -create table d1.t984(n int); -create table d1.t983(n int); -create table d1.t982(n int); -create table d1.t981(n int); -create table d1.t980(n int); -create table d1.t979(n int); -create table d1.t978(n int); -create table d1.t977(n int); -create table d1.t976(n int); -create table d1.t975(n int); -create table d1.t974(n int); -create table d1.t973(n int); -create table d1.t972(n int); -create table d1.t971(n int); -create table d1.t970(n int); -create table d1.t969(n int); -create table d1.t968(n int); -create table d1.t967(n int); -create table d1.t966(n int); -create table d1.t965(n int); -create table d1.t964(n int); -create table d1.t963(n int); -create table d1.t962(n int); -create table d1.t961(n int); -create table d1.t960(n int); -create table d1.t959(n int); -create table d1.t958(n int); -create table d1.t957(n int); -create table d1.t956(n int); -create table d1.t955(n int); -create table d1.t954(n int); -create table d1.t953(n int); -create table d1.t952(n int); -create table d1.t951(n int); -create table d1.t950(n int); -create table d1.t949(n int); -create table d1.t948(n int); -create table d1.t947(n int); -create table d1.t946(n int); -create table d1.t945(n int); -create table d1.t944(n int); -create table d1.t943(n int); -create table d1.t942(n int); -create table d1.t941(n int); -create table d1.t940(n int); -create table d1.t939(n int); -create table d1.t938(n int); -create table d1.t937(n int); -create table d1.t936(n int); -create table d1.t935(n int); -create table d1.t934(n int); -create table d1.t933(n int); -create table d1.t932(n int); -create table d1.t931(n int); -create table d1.t930(n int); -create table d1.t929(n int); -create table d1.t928(n int); -create table d1.t927(n int); -create table d1.t926(n int); -create table d1.t925(n int); -create table d1.t924(n int); -create table d1.t923(n int); -create table d1.t922(n int); -create table d1.t921(n int); -create table d1.t920(n int); -create table d1.t919(n int); -create table d1.t918(n int); -create table d1.t917(n int); -create table d1.t916(n int); -create table d1.t915(n int); -create table d1.t914(n int); -create table d1.t913(n int); -create table d1.t912(n int); -create table d1.t911(n int); -create table d1.t910(n int); -create table d1.t909(n int); -create table d1.t908(n int); -create table d1.t907(n int); -create table d1.t906(n int); -create table d1.t905(n int); -create table d1.t904(n int); -create table d1.t903(n int); -create table d1.t902(n int); -create table d1.t901(n int); -create table d1.t900(n int); -create table d1.t899(n int); -create table d1.t898(n int); -create table d1.t897(n int); -create table d1.t896(n int); -create table d1.t895(n int); -create table d1.t894(n int); -create table d1.t893(n int); -create table d1.t892(n int); -create table d1.t891(n int); -create table d1.t890(n int); -create table d1.t889(n int); -create table d1.t888(n int); -create table d1.t887(n int); -create table d1.t886(n int); -create table d1.t885(n int); -create table d1.t884(n int); -create table d1.t883(n int); -create table d1.t882(n int); -create table d1.t881(n int); -create table d1.t880(n int); -create table d1.t879(n int); -create table d1.t878(n int); -create table d1.t877(n int); -create table d1.t876(n int); -create table d1.t875(n int); -create table d1.t874(n int); -create table d1.t873(n int); -create table d1.t872(n int); -create table d1.t871(n int); -create table d1.t870(n int); -create table d1.t869(n int); -create table d1.t868(n int); -create table d1.t867(n int); -create table d1.t866(n int); -create table d1.t865(n int); -create table d1.t864(n int); -create table d1.t863(n int); -create table d1.t862(n int); -create table d1.t861(n int); -create table d1.t860(n int); -create table d1.t859(n int); -create table d1.t858(n int); -create table d1.t857(n int); -create table d1.t856(n int); -create table d1.t855(n int); -create table d1.t854(n int); -create table d1.t853(n int); -create table d1.t852(n int); -create table d1.t851(n int); -create table d1.t850(n int); -create table d1.t849(n int); -create table d1.t848(n int); -create table d1.t847(n int); -create table d1.t846(n int); -create table d1.t845(n int); -create table d1.t844(n int); -create table d1.t843(n int); -create table d1.t842(n int); -create table d1.t841(n int); -create table d1.t840(n int); -create table d1.t839(n int); -create table d1.t838(n int); -create table d1.t837(n int); -create table d1.t836(n int); -create table d1.t835(n int); -create table d1.t834(n int); -create table d1.t833(n int); -create table d1.t832(n int); -create table d1.t831(n int); -create table d1.t830(n int); -create table d1.t829(n int); -create table d1.t828(n int); -create table d1.t827(n int); -create table d1.t826(n int); -create table d1.t825(n int); -create table d1.t824(n int); -create table d1.t823(n int); -create table d1.t822(n int); -create table d1.t821(n int); -create table d1.t820(n int); -create table d1.t819(n int); -create table d1.t818(n int); -create table d1.t817(n int); -create table d1.t816(n int); -create table d1.t815(n int); -create table d1.t814(n int); -create table d1.t813(n int); -create table d1.t812(n int); -create table d1.t811(n int); -create table d1.t810(n int); -create table d1.t809(n int); -create table d1.t808(n int); -create table d1.t807(n int); -create table d1.t806(n int); -create table d1.t805(n int); -create table d1.t804(n int); -create table d1.t803(n int); -create table d1.t802(n int); -create table d1.t801(n int); -create table d1.t800(n int); -create table d1.t799(n int); -create table d1.t798(n int); -create table d1.t797(n int); -create table d1.t796(n int); -create table d1.t795(n int); -create table d1.t794(n int); -create table d1.t793(n int); -create table d1.t792(n int); -create table d1.t791(n int); -create table d1.t790(n int); -create table d1.t789(n int); -create table d1.t788(n int); -create table d1.t787(n int); -create table d1.t786(n int); -create table d1.t785(n int); -create table d1.t784(n int); -create table d1.t783(n int); -create table d1.t782(n int); -create table d1.t781(n int); -create table d1.t780(n int); -create table d1.t779(n int); -create table d1.t778(n int); -create table d1.t777(n int); -create table d1.t776(n int); -create table d1.t775(n int); -create table d1.t774(n int); -create table d1.t773(n int); -create table d1.t772(n int); -create table d1.t771(n int); -create table d1.t770(n int); -create table d1.t769(n int); -create table d1.t768(n int); -create table d1.t767(n int); -create table d1.t766(n int); -create table d1.t765(n int); -create table d1.t764(n int); -create table d1.t763(n int); -create table d1.t762(n int); -create table d1.t761(n int); -create table d1.t760(n int); -create table d1.t759(n int); -create table d1.t758(n int); -create table d1.t757(n int); -create table d1.t756(n int); -create table d1.t755(n int); -create table d1.t754(n int); -create table d1.t753(n int); -create table d1.t752(n int); -create table d1.t751(n int); -create table d1.t750(n int); -create table d1.t749(n int); -create table d1.t748(n int); -create table d1.t747(n int); -create table d1.t746(n int); -create table d1.t745(n int); -create table d1.t744(n int); -create table d1.t743(n int); -create table d1.t742(n int); -create table d1.t741(n int); -create table d1.t740(n int); -create table d1.t739(n int); -create table d1.t738(n int); -create table d1.t737(n int); -create table d1.t736(n int); -create table d1.t735(n int); -create table d1.t734(n int); -create table d1.t733(n int); -create table d1.t732(n int); -create table d1.t731(n int); -create table d1.t730(n int); -create table d1.t729(n int); -create table d1.t728(n int); -create table d1.t727(n int); -create table d1.t726(n int); -create table d1.t725(n int); -create table d1.t724(n int); -create table d1.t723(n int); -create table d1.t722(n int); -create table d1.t721(n int); -create table d1.t720(n int); -create table d1.t719(n int); -create table d1.t718(n int); -create table d1.t717(n int); -create table d1.t716(n int); -create table d1.t715(n int); -create table d1.t714(n int); -create table d1.t713(n int); -create table d1.t712(n int); -create table d1.t711(n int); -create table d1.t710(n int); -create table d1.t709(n int); -create table d1.t708(n int); -create table d1.t707(n int); -create table d1.t706(n int); -create table d1.t705(n int); -create table d1.t704(n int); -create table d1.t703(n int); -create table d1.t702(n int); -create table d1.t701(n int); -create table d1.t700(n int); -create table d1.t699(n int); -create table d1.t698(n int); -create table d1.t697(n int); -create table d1.t696(n int); -create table d1.t695(n int); -create table d1.t694(n int); -create table d1.t693(n int); -create table d1.t692(n int); -create table d1.t691(n int); -create table d1.t690(n int); -create table d1.t689(n int); -create table d1.t688(n int); -create table d1.t687(n int); -create table d1.t686(n int); -create table d1.t685(n int); -create table d1.t684(n int); -create table d1.t683(n int); -create table d1.t682(n int); -create table d1.t681(n int); -create table d1.t680(n int); -create table d1.t679(n int); -create table d1.t678(n int); -create table d1.t677(n int); -create table d1.t676(n int); -create table d1.t675(n int); -create table d1.t674(n int); -create table d1.t673(n int); -create table d1.t672(n int); -create table d1.t671(n int); -create table d1.t670(n int); -create table d1.t669(n int); -create table d1.t668(n int); -create table d1.t667(n int); -create table d1.t666(n int); -create table d1.t665(n int); -create table d1.t664(n int); -create table d1.t663(n int); -create table d1.t662(n int); -create table d1.t661(n int); -create table d1.t660(n int); -create table d1.t659(n int); -create table d1.t658(n int); -create table d1.t657(n int); -create table d1.t656(n int); -create table d1.t655(n int); -create table d1.t654(n int); -create table d1.t653(n int); -create table d1.t652(n int); -create table d1.t651(n int); -create table d1.t650(n int); -create table d1.t649(n int); -create table d1.t648(n int); -create table d1.t647(n int); -create table d1.t646(n int); -create table d1.t645(n int); -create table d1.t644(n int); -create table d1.t643(n int); -create table d1.t642(n int); -create table d1.t641(n int); -create table d1.t640(n int); -create table d1.t639(n int); -create table d1.t638(n int); -create table d1.t637(n int); -create table d1.t636(n int); -create table d1.t635(n int); -create table d1.t634(n int); -create table d1.t633(n int); -create table d1.t632(n int); -create table d1.t631(n int); -create table d1.t630(n int); -create table d1.t629(n int); -create table d1.t628(n int); -create table d1.t627(n int); -create table d1.t626(n int); -create table d1.t625(n int); -create table d1.t624(n int); -create table d1.t623(n int); -create table d1.t622(n int); -create table d1.t621(n int); -create table d1.t620(n int); -create table d1.t619(n int); -create table d1.t618(n int); -create table d1.t617(n int); -create table d1.t616(n int); -create table d1.t615(n int); -create table d1.t614(n int); -create table d1.t613(n int); -create table d1.t612(n int); -create table d1.t611(n int); -create table d1.t610(n int); -create table d1.t609(n int); -create table d1.t608(n int); -create table d1.t607(n int); -create table d1.t606(n int); -create table d1.t605(n int); -create table d1.t604(n int); -create table d1.t603(n int); -create table d1.t602(n int); -create table d1.t601(n int); -create table d1.t600(n int); -create table d1.t599(n int); -create table d1.t598(n int); -create table d1.t597(n int); -create table d1.t596(n int); -create table d1.t595(n int); -create table d1.t594(n int); -create table d1.t593(n int); -create table d1.t592(n int); -create table d1.t591(n int); -create table d1.t590(n int); -create table d1.t589(n int); -create table d1.t588(n int); -create table d1.t587(n int); -create table d1.t586(n int); -create table d1.t585(n int); -create table d1.t584(n int); -create table d1.t583(n int); -create table d1.t582(n int); -create table d1.t581(n int); -create table d1.t580(n int); -create table d1.t579(n int); -create table d1.t578(n int); -create table d1.t577(n int); -create table d1.t576(n int); -create table d1.t575(n int); -create table d1.t574(n int); -create table d1.t573(n int); -create table d1.t572(n int); -create table d1.t571(n int); -create table d1.t570(n int); -create table d1.t569(n int); -create table d1.t568(n int); -create table d1.t567(n int); -create table d1.t566(n int); -create table d1.t565(n int); -create table d1.t564(n int); -create table d1.t563(n int); -create table d1.t562(n int); -create table d1.t561(n int); -create table d1.t560(n int); -create table d1.t559(n int); -create table d1.t558(n int); -create table d1.t557(n int); -create table d1.t556(n int); -create table d1.t555(n int); -create table d1.t554(n int); -create table d1.t553(n int); -create table d1.t552(n int); -create table d1.t551(n int); -create table d1.t550(n int); -create table d1.t549(n int); -create table d1.t548(n int); -create table d1.t547(n int); -create table d1.t546(n int); -create table d1.t545(n int); -create table d1.t544(n int); -create table d1.t543(n int); -create table d1.t542(n int); -create table d1.t541(n int); -create table d1.t540(n int); -create table d1.t539(n int); -create table d1.t538(n int); -create table d1.t537(n int); -create table d1.t536(n int); -create table d1.t535(n int); -create table d1.t534(n int); -create table d1.t533(n int); -create table d1.t532(n int); -create table d1.t531(n int); -create table d1.t530(n int); -create table d1.t529(n int); -create table d1.t528(n int); -create table d1.t527(n int); -create table d1.t526(n int); -create table d1.t525(n int); -create table d1.t524(n int); -create table d1.t523(n int); -create table d1.t522(n int); -create table d1.t521(n int); -create table d1.t520(n int); -create table d1.t519(n int); -create table d1.t518(n int); -create table d1.t517(n int); -create table d1.t516(n int); -create table d1.t515(n int); -create table d1.t514(n int); -create table d1.t513(n int); -create table d1.t512(n int); -create table d1.t511(n int); -create table d1.t510(n int); -create table d1.t509(n int); -create table d1.t508(n int); -create table d1.t507(n int); -create table d1.t506(n int); -create table d1.t505(n int); -create table d1.t504(n int); -create table d1.t503(n int); -create table d1.t502(n int); -create table d1.t501(n int); -create table d1.t500(n int); -create table d1.t499(n int); -create table d1.t498(n int); -create table d1.t497(n int); -create table d1.t496(n int); -create table d1.t495(n int); -create table d1.t494(n int); -create table d1.t493(n int); -create table d1.t492(n int); -create table d1.t491(n int); -create table d1.t490(n int); -create table d1.t489(n int); -create table d1.t488(n int); -create table d1.t487(n int); -create table d1.t486(n int); -create table d1.t485(n int); -create table d1.t484(n int); -create table d1.t483(n int); -create table d1.t482(n int); -create table d1.t481(n int); -create table d1.t480(n int); -create table d1.t479(n int); -create table d1.t478(n int); -create table d1.t477(n int); -create table d1.t476(n int); -create table d1.t475(n int); -create table d1.t474(n int); -create table d1.t473(n int); -create table d1.t472(n int); -create table d1.t471(n int); -create table d1.t470(n int); -create table d1.t469(n int); -create table d1.t468(n int); -create table d1.t467(n int); -create table d1.t466(n int); -create table d1.t465(n int); -create table d1.t464(n int); -create table d1.t463(n int); -create table d1.t462(n int); -create table d1.t461(n int); -create table d1.t460(n int); -create table d1.t459(n int); -create table d1.t458(n int); -create table d1.t457(n int); -create table d1.t456(n int); -create table d1.t455(n int); -create table d1.t454(n int); -create table d1.t453(n int); -create table d1.t452(n int); -create table d1.t451(n int); -create table d1.t450(n int); -create table d1.t449(n int); -create table d1.t448(n int); -create table d1.t447(n int); -create table d1.t446(n int); -create table d1.t445(n int); -create table d1.t444(n int); -create table d1.t443(n int); -create table d1.t442(n int); -create table d1.t441(n int); -create table d1.t440(n int); -create table d1.t439(n int); -create table d1.t438(n int); -create table d1.t437(n int); -create table d1.t436(n int); -create table d1.t435(n int); -create table d1.t434(n int); -create table d1.t433(n int); -create table d1.t432(n int); -create table d1.t431(n int); -create table d1.t430(n int); -create table d1.t429(n int); -create table d1.t428(n int); -create table d1.t427(n int); -create table d1.t426(n int); -create table d1.t425(n int); -create table d1.t424(n int); -create table d1.t423(n int); -create table d1.t422(n int); -create table d1.t421(n int); -create table d1.t420(n int); -create table d1.t419(n int); -create table d1.t418(n int); -create table d1.t417(n int); -create table d1.t416(n int); -create table d1.t415(n int); -create table d1.t414(n int); -create table d1.t413(n int); -create table d1.t412(n int); -create table d1.t411(n int); -create table d1.t410(n int); -create table d1.t409(n int); -create table d1.t408(n int); -create table d1.t407(n int); -create table d1.t406(n int); -create table d1.t405(n int); -create table d1.t404(n int); -create table d1.t403(n int); -create table d1.t402(n int); -create table d1.t401(n int); -create table d1.t400(n int); -create table d1.t399(n int); -create table d1.t398(n int); -create table d1.t397(n int); -create table d1.t396(n int); -create table d1.t395(n int); -create table d1.t394(n int); -create table d1.t393(n int); -create table d1.t392(n int); -create table d1.t391(n int); -create table d1.t390(n int); -create table d1.t389(n int); -create table d1.t388(n int); -create table d1.t387(n int); -create table d1.t386(n int); -create table d1.t385(n int); -create table d1.t384(n int); -create table d1.t383(n int); -create table d1.t382(n int); -create table d1.t381(n int); -create table d1.t380(n int); -create table d1.t379(n int); -create table d1.t378(n int); -create table d1.t377(n int); -create table d1.t376(n int); -create table d1.t375(n int); -create table d1.t374(n int); -create table d1.t373(n int); -create table d1.t372(n int); -create table d1.t371(n int); -create table d1.t370(n int); -create table d1.t369(n int); -create table d1.t368(n int); -create table d1.t367(n int); -create table d1.t366(n int); -create table d1.t365(n int); -create table d1.t364(n int); -create table d1.t363(n int); -create table d1.t362(n int); -create table d1.t361(n int); -create table d1.t360(n int); -create table d1.t359(n int); -create table d1.t358(n int); -create table d1.t357(n int); -create table d1.t356(n int); -create table d1.t355(n int); -create table d1.t354(n int); -create table d1.t353(n int); -create table d1.t352(n int); -create table d1.t351(n int); -create table d1.t350(n int); -create table d1.t349(n int); -create table d1.t348(n int); -create table d1.t347(n int); -create table d1.t346(n int); -create table d1.t345(n int); -create table d1.t344(n int); -create table d1.t343(n int); -create table d1.t342(n int); -create table d1.t341(n int); -create table d1.t340(n int); -create table d1.t339(n int); -create table d1.t338(n int); -create table d1.t337(n int); -create table d1.t336(n int); -create table d1.t335(n int); -create table d1.t334(n int); -create table d1.t333(n int); -create table d1.t332(n int); -create table d1.t331(n int); -create table d1.t330(n int); -create table d1.t329(n int); -create table d1.t328(n int); -create table d1.t327(n int); -create table d1.t326(n int); -create table d1.t325(n int); -create table d1.t324(n int); -create table d1.t323(n int); -create table d1.t322(n int); -create table d1.t321(n int); -create table d1.t320(n int); -create table d1.t319(n int); -create table d1.t318(n int); -create table d1.t317(n int); -create table d1.t316(n int); -create table d1.t315(n int); -create table d1.t314(n int); -create table d1.t313(n int); -create table d1.t312(n int); -create table d1.t311(n int); -create table d1.t310(n int); -create table d1.t309(n int); -create table d1.t308(n int); -create table d1.t307(n int); -create table d1.t306(n int); -create table d1.t305(n int); -create table d1.t304(n int); -create table d1.t303(n int); -create table d1.t302(n int); -create table d1.t301(n int); -create table d1.t300(n int); -create table d1.t299(n int); -create table d1.t298(n int); -create table d1.t297(n int); -create table d1.t296(n int); -create table d1.t295(n int); -create table d1.t294(n int); -create table d1.t293(n int); -create table d1.t292(n int); -create table d1.t291(n int); -create table d1.t290(n int); -create table d1.t289(n int); -create table d1.t288(n int); -create table d1.t287(n int); -create table d1.t286(n int); -create table d1.t285(n int); -create table d1.t284(n int); -create table d1.t283(n int); -create table d1.t282(n int); -create table d1.t281(n int); -create table d1.t280(n int); -create table d1.t279(n int); -create table d1.t278(n int); -create table d1.t277(n int); -create table d1.t276(n int); -create table d1.t275(n int); -create table d1.t274(n int); -create table d1.t273(n int); -create table d1.t272(n int); -create table d1.t271(n int); -create table d1.t270(n int); -create table d1.t269(n int); -create table d1.t268(n int); -create table d1.t267(n int); -create table d1.t266(n int); -create table d1.t265(n int); -create table d1.t264(n int); -create table d1.t263(n int); -create table d1.t262(n int); -create table d1.t261(n int); -create table d1.t260(n int); -create table d1.t259(n int); -create table d1.t258(n int); -create table d1.t257(n int); -create table d1.t256(n int); -create table d1.t255(n int); -create table d1.t254(n int); -create table d1.t253(n int); -create table d1.t252(n int); -create table d1.t251(n int); -create table d1.t250(n int); -create table d1.t249(n int); -create table d1.t248(n int); -create table d1.t247(n int); -create table d1.t246(n int); -create table d1.t245(n int); -create table d1.t244(n int); -create table d1.t243(n int); -create table d1.t242(n int); -create table d1.t241(n int); -create table d1.t240(n int); -create table d1.t239(n int); -create table d1.t238(n int); -create table d1.t237(n int); -create table d1.t236(n int); -create table d1.t235(n int); -create table d1.t234(n int); -create table d1.t233(n int); -create table d1.t232(n int); -create table d1.t231(n int); -create table d1.t230(n int); -create table d1.t229(n int); -create table d1.t228(n int); -create table d1.t227(n int); -create table d1.t226(n int); -create table d1.t225(n int); -create table d1.t224(n int); -create table d1.t223(n int); -create table d1.t222(n int); -create table d1.t221(n int); -create table d1.t220(n int); -create table d1.t219(n int); -create table d1.t218(n int); -create table d1.t217(n int); -create table d1.t216(n int); -create table d1.t215(n int); -create table d1.t214(n int); -create table d1.t213(n int); -create table d1.t212(n int); -create table d1.t211(n int); -create table d1.t210(n int); -create table d1.t209(n int); -create table d1.t208(n int); -create table d1.t207(n int); -create table d1.t206(n int); -create table d1.t205(n int); -create table d1.t204(n int); -create table d1.t203(n int); -create table d1.t202(n int); -create table d1.t201(n int); -create table d1.t200(n int); -create table d1.t199(n int); -create table d1.t198(n int); -create table d1.t197(n int); -create table d1.t196(n int); -create table d1.t195(n int); -create table d1.t194(n int); -create table d1.t193(n int); -create table d1.t192(n int); -create table d1.t191(n int); -create table d1.t190(n int); -create table d1.t189(n int); -create table d1.t188(n int); -create table d1.t187(n int); -create table d1.t186(n int); -create table d1.t185(n int); -create table d1.t184(n int); -create table d1.t183(n int); -create table d1.t182(n int); -create table d1.t181(n int); -create table d1.t180(n int); -create table d1.t179(n int); -create table d1.t178(n int); -create table d1.t177(n int); -create table d1.t176(n int); -create table d1.t175(n int); -create table d1.t174(n int); -create table d1.t173(n int); -create table d1.t172(n int); -create table d1.t171(n int); -create table d1.t170(n int); -create table d1.t169(n int); -create table d1.t168(n int); -create table d1.t167(n int); -create table d1.t166(n int); -create table d1.t165(n int); -create table d1.t164(n int); -create table d1.t163(n int); -create table d1.t162(n int); -create table d1.t161(n int); -create table d1.t160(n int); -create table d1.t159(n int); -create table d1.t158(n int); -create table d1.t157(n int); -create table d1.t156(n int); -create table d1.t155(n int); -create table d1.t154(n int); -create table d1.t153(n int); -create table d1.t152(n int); -create table d1.t151(n int); -create table d1.t150(n int); -create table d1.t149(n int); -create table d1.t148(n int); -create table d1.t147(n int); -create table d1.t146(n int); -create table d1.t145(n int); -create table d1.t144(n int); -create table d1.t143(n int); -create table d1.t142(n int); -create table d1.t141(n int); -create table d1.t140(n int); -create table d1.t139(n int); -create table d1.t138(n int); -create table d1.t137(n int); -create table d1.t136(n int); -create table d1.t135(n int); -create table d1.t134(n int); -create table d1.t133(n int); -create table d1.t132(n int); -create table d1.t131(n int); -create table d1.t130(n int); -create table d1.t129(n int); -create table d1.t128(n int); -create table d1.t127(n int); -create table d1.t126(n int); -create table d1.t125(n int); -create table d1.t124(n int); -create table d1.t123(n int); -create table d1.t122(n int); -create table d1.t121(n int); -create table d1.t120(n int); -create table d1.t119(n int); -create table d1.t118(n int); -create table d1.t117(n int); -create table d1.t116(n int); -create table d1.t115(n int); -create table d1.t114(n int); -create table d1.t113(n int); -create table d1.t112(n int); -create table d1.t111(n int); -create table d1.t110(n int); -create table d1.t109(n int); -create table d1.t108(n int); -create table d1.t107(n int); -create table d1.t106(n int); -create table d1.t105(n int); -create table d1.t104(n int); -create table d1.t103(n int); -create table d1.t102(n int); -create table d1.t101(n int); -create table d1.t100(n int); -create table d1.t99(n int); -create table d1.t98(n int); -create table d1.t97(n int); -create table d1.t96(n int); -create table d1.t95(n int); -create table d1.t94(n int); -create table d1.t93(n int); -create table d1.t92(n int); -create table d1.t91(n int); -create table d1.t90(n int); -create table d1.t89(n int); -create table d1.t88(n int); -create table d1.t87(n int); -create table d1.t86(n int); -create table d1.t85(n int); -create table d1.t84(n int); -create table d1.t83(n int); -create table d1.t82(n int); -create table d1.t81(n int); -create table d1.t80(n int); -create table d1.t79(n int); -create table d1.t78(n int); -create table d1.t77(n int); -create table d1.t76(n int); -create table d1.t75(n int); -create table d1.t74(n int); -create table d1.t73(n int); -create table d1.t72(n int); -create table d1.t71(n int); -create table d1.t70(n int); -create table d1.t69(n int); -create table d1.t68(n int); -create table d1.t67(n int); -create table d1.t66(n int); -create table d1.t65(n int); -create table d1.t64(n int); -create table d1.t63(n int); -create table d1.t62(n int); -create table d1.t61(n int); -create table d1.t60(n int); -create table d1.t59(n int); -create table d1.t58(n int); -create table d1.t57(n int); -create table d1.t56(n int); -create table d1.t55(n int); -create table d1.t54(n int); -create table d1.t53(n int); -create table d1.t52(n int); -create table d1.t51(n int); -create table d1.t50(n int); -create table d1.t49(n int); -create table d1.t48(n int); -create table d1.t47(n int); -create table d1.t46(n int); -create table d1.t45(n int); -create table d1.t44(n int); -create table d1.t43(n int); -create table d1.t42(n int); -create table d1.t41(n int); -create table d1.t40(n int); -create table d1.t39(n int); -create table d1.t38(n int); -create table d1.t37(n int); -create table d1.t36(n int); -create table d1.t35(n int); -create table d1.t34(n int); -create table d1.t33(n int); -create table d1.t32(n int); -create table d1.t31(n int); -create table d1.t30(n int); -create table d1.t29(n int); -create table d1.t28(n int); -create table d1.t27(n int); -create table d1.t26(n int); -create table d1.t25(n int); -create table d1.t24(n int); -create table d1.t23(n int); -create table d1.t22(n int); -create table d1.t21(n int); -create table d1.t20(n int); -create table d1.t19(n int); -create table d1.t18(n int); -create table d1.t17(n int); -create table d1.t16(n int); -create table d1.t15(n int); -create table d1.t14(n int); -create table d1.t13(n int); -create table d1.t12(n int); -create table d1.t11(n int); -create table d1.t10(n int); -create table d1.t9(n int); -create table d1.t8(n int); -create table d1.t7(n int); -create table d1.t6(n int); -create table d1.t5(n int); -create table d1.t4(n int); -create table d1.t3(n int); -create table d1.t2(n int); -create table d1.t1(n int); -drop database d1; -ERROR HY000: Error dropping database (can't rmdir './d1/', errno: 17) -use d1; +Tables_in_mysqltest +drop database mysqltest; +ERROR HY000: Error dropping database (can't rmdir './mysqltest/', errno: 17) +use mysqltest; show tables; -Tables_in_d1 +Tables_in_mysqltest use test; create table t1 (n int); insert into t1 values (1234); -use d1; +use mysqltest; show tables; -Tables_in_d1 +Tables_in_mysqltest use test; select * from t1; n diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test index 8f471ebb979..8e6c53af095 100644 --- a/mysql-test/t/ctype_cp932.test +++ b/mysql-test/t/ctype_cp932.test @@ -419,7 +419,7 @@ SET @var1= x'8300'; # exercise this code from mysql-test-run. EXECUTE stmt1 USING @var1; --replace_column 2 # 5 # -SHOW BINLOG EVENTS; +SHOW BINLOG EVENTS FROM 79; SELECT HEX(f1) FROM t1; DROP table t1; # end test for bug#11338 diff --git a/mysql-test/t/rpl_drop_db.test b/mysql-test/t/rpl_drop_db.test index 71dc22f705f..7b4a56910d6 100644 --- a/mysql-test/t/rpl_drop_db.test +++ b/mysql-test/t/rpl_drop_db.test @@ -5,30 +5,32 @@ connection master; --disable_warnings -drop database if exists d1; +drop database if exists mysqltest; --enable_warnings -create database d1; -create table d1.t1 (n int); -insert into d1.t1 values (1); -select * from d1.t1 into outfile 'd1/f1.txt'; -create table d1.t2 (n int); -create table d1.t3 (n int); +create database mysqltest; +create table mysqltest.t1 (n int); +insert into mysqltest.t1 values (1); +select * from mysqltest.t1 into outfile 'mysqltest/f1.txt'; +create table mysqltest.t2 (n int); +create table mysqltest.t3 (n int); --error 1010 -drop database d1; -use d1; +drop database mysqltest; +use mysqltest; show tables; # test the branch of the code that deals with the query buffer overflow -let $1=1000; +disable_query_log; +let $1=50; while ($1) { - eval create table d1.t$1(n int); + eval create table mysqltest.mysql_test_long_table_name$1 (n int); dec $1; } +enable_query_log; --error 1010 -drop database d1; -use d1; +drop database mysqltest; +use mysqltest; show tables; use test; create table t1 (n int); @@ -36,7 +38,7 @@ insert into t1 values (1234); sync_slave_with_master; connection slave; -use d1; +use mysqltest; show tables; use test; select * from t1; @@ -48,5 +50,7 @@ sync_slave_with_master; #cleanup connection slave; stop slave; -system rm -rf var/master-data/d1; +system rm -rf var/master-data/mysqltest; + +# End of 4.1 tests diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6dcc7be0904..a279fae93a9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -33,12 +33,8 @@ static TYPELIB deletable_extentions= static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level, - TABLE_LIST** dropped_tables); + TABLE_LIST **dropped_tables); - -static inline void write_to_binlog(THD* thd, char* query, uint q_len, - char* db, uint db_len); - /* Database options hash */ static HASH dboptions; static my_bool dboptions_init= 0; @@ -56,6 +52,7 @@ typedef struct my_dbopt_st /* Function we use in the creation of our hash to get key. */ + static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, my_bool not_used __attribute__((unused))) { @@ -63,17 +60,19 @@ static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, return (byte*) opt->name; } + /* - Helper function to write a query to binlog used by mysql_rm_db() - */ -static inline void write_to_binlog(THD* thd, char* query, uint q_len, - char* db, uint db_len) + Helper function to write a query to binlog used by mysql_rm_db() +*/ + +static inline void write_to_binlog(THD *thd, char *query, uint q_len, + char *db, uint db_len) { - Query_log_event qinfo(thd, query, q_len, 0, 0); - qinfo.error_code= 0; - qinfo.db= db; - qinfo.db_len= db_len; - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, query, q_len, 0, 0); + qinfo.error_code= 0; + qinfo.db= db; + qinfo.db_len= db_len; + mysql_bin_log.write(&qinfo); } @@ -644,7 +643,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) error= -1; if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0, - &dropped_tables)) >= 0) + &dropped_tables)) >= 0) { ha_drop_database(path); query_cache_invalidate1(db); @@ -696,42 +695,40 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } else if (mysql_bin_log.is_open()) { - char* query= thd->alloc(MAX_DROP_TABLE_Q_LEN); + char *query, *query_pos, *query_end, *query_data_start; + TABLE_LIST *tbl; + uint db_len; + + if (!(query= thd->alloc(MAX_DROP_TABLE_Q_LEN))) + goto exit; /* not much else we can do */ + query_pos= query_data_start= strmov(query,"drop table "); + query_end= query + MAX_DROP_TABLE_Q_LEN; + db_len= strlen(db); - if (!query) - goto exit; /* not much else we can do */ - char* p= strmov(query,"drop table "); - char* p_end= query + MAX_DROP_TABLE_Q_LEN; - TABLE_LIST* tbl; - bool last_query_needs_write= 0; - uint db_len= strlen(db); - - for (tbl= dropped_tables;tbl;tbl= tbl->next) - { - if (!tbl->was_dropped) - continue; + for (tbl= dropped_tables; tbl; tbl= tbl->next) + { + uint tbl_name_len; + if (!tbl->was_dropped) + continue; - /* 3 for the quotes and the comma*/ - uint tbl_name_len= strlen(tbl->real_name) + 3; - if (p + tbl_name_len + 1 >= p_end) - { - *--p= 0; /* kill , */ - write_to_binlog(thd, query, p - query, db, db_len); - p= query + 11; /* reuse the initial "drop table" */ - } + /* 3 for the quotes and the comma*/ + tbl_name_len= strlen(tbl->real_name) + 3; + if (query_pos + tbl_name_len + 1 >= query_end) + { + write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + query_pos= query_data_start; + } - *p++ = '`'; - p= strmov(p,tbl->real_name); - *p++ = '`'; - *p++ = ','; - last_query_needs_write= 1; - } + *query_pos++ = '`'; + query_pos= strmov(query_pos,tbl->real_name); + *query_pos++ = '`'; + *query_pos++ = ','; + } - if (last_query_needs_write) - { - *--p= 0; - write_to_binlog(thd, query, p - query, db, db_len); - } + if (query_pos != query_data_start) + { + write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + } } exit: @@ -777,7 +774,8 @@ exit2: */ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, - const char *org_path, uint level, TABLE_LIST** dropped_tables) + const char *org_path, uint level, + TABLE_LIST **dropped_tables) { long deleted=0; ulong found_other_files=0; From 9017addfd8e0a232b24bfe61aa9821feb45350bb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 23:44:42 +0400 Subject: [PATCH 65/80] Correction of fix for bug #12280 "Triggers: crash if flush tables". We should not assume that "thd" argument of reload_acl_and_cache() is non-zero. Failure to do so will cause server to crash when one sends SIGHUP to it. sql/sql_parse.cc: reload_acl_and_cache(): When we call this function from SIGHUP handler we pass 0 as "thd" argument to it. So we should not assume that thd is non-zero in it. --- sql/sql_parse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 70920b07a97..c86b7eba024 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6517,7 +6517,7 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List *using_fields) SYNOPSIS reload_acl_and_cache() - thd Thread handler + thd Thread handler (can be NULL!) options What should be reset/reloaded (tables, privileges, slave...) tables Tables to flush (if any) @@ -6539,7 +6539,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, select_errors=0; /* Write if more errors */ bool tmp_write_to_binlog= 1; - if (thd->in_sub_stmt) + if (thd && thd->in_sub_stmt) { my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); return 1; From d2aa6e78ac758c739e25021360a3432f480b43e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 00:21:47 +0300 Subject: [PATCH 66/80] Cleanups during review of new code Removed ASSERT that can obviously never be wrong --- sql/sql_base.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a7f5fa3ce03..d742147db27 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2945,9 +2945,15 @@ find_field_in_tables(THD *thd, Item_ident *item, char name_buff[NAME_LEN+1]; TABLE_LIST *cur_table= first_table; TABLE_LIST *actual_table; - bool is_qualified= table_name && table_name[0]; - bool allow_rowid= is_qualified ? - TRUE : (cur_table && !cur_table->next_local); + bool allow_rowid; + + if (!table_name || !table_name[0]) + { + table_name= 0; // For easier test + db= 0; + } + + allow_rowid= table_name || (cur_table && !cur_table->next_local); if (item->cached_table) { @@ -3022,8 +3028,7 @@ find_field_in_tables(THD *thd, Item_ident *item, cur_table= cur_table->next_name_resolution_table) { Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name, - is_qualified ? table_name : NULL, - is_qualified ? db : NULL, + table_name, db, length, ref, (cur_table->table && test(cur_table->table->grant. @@ -3053,7 +3058,7 @@ find_field_in_tables(THD *thd, Item_ident *item, If we found a fully qualified field we return it directly as it can't have duplicates. */ - if (is_qualified && db) + if (db) return cur_field; if (found) @@ -3061,7 +3066,7 @@ find_field_in_tables(THD *thd, Item_ident *item, if (report_error == REPORT_ALL_ERRORS || report_error == IGNORE_EXCEPT_NON_UNIQUE) my_error(ER_NON_UNIQ_ERROR, MYF(0), - is_qualified ? item->full_name() : name, thd->where); + table_name ? item->full_name() : name, thd->where); return (Field*) 0; } found= cur_field; @@ -3078,7 +3083,7 @@ find_field_in_tables(THD *thd, Item_ident *item, and cur_table wouldn't be updated by the loop increment part, so it will be equal to the first table. */ - if (is_qualified && (cur_table == first_table) && + if (table_name && (cur_table == first_table) && (report_error == REPORT_ALL_ERRORS || report_error == REPORT_EXCEPT_NON_UNIQUE)) { @@ -3091,13 +3096,13 @@ find_field_in_tables(THD *thd, Item_ident *item, my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where); } else + { if (report_error == REPORT_ALL_ERRORS || report_error == REPORT_EXCEPT_NON_UNIQUE) my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where); else found= not_found_field; - - DBUG_ASSERT(!found || found == not_found_field); + } return found; } From da13a76a289a7f75089c738cb08745e7dd82f619 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 15:50:58 -0700 Subject: [PATCH 67/80] Make SYSDATE() behave as in Oracle: always the current datetime, not the datetime of when the current statement began. This also makes SYSDATE() not safe in replication. (Bug #12562) mysql-test/r/func_time.result: Add new results mysql-test/t/func_time.test: Add tests for new SYSDATE() behavior sql/item_timefunc.cc: Add Item_func_sysdate_local implementation sql/item_timefunc.h: Add Item_func_sysdate_local, so SYSDATE() can behave differently than NOW(). sql/lex.h: SYSDATE() is no longer an alias for NOW(). sql/sql_yacc.yy: Handle SYSDATE() --- mysql-test/r/func_time.result | 40 +++++++++++++++++++++ mysql-test/t/func_time.test | 52 +++++++++++++++++++++++++++ sql/item_timefunc.cc | 68 +++++++++++++++++++++++++++++++++-- sql/item_timefunc.h | 27 ++++++++++++++ sql/lex.h | 2 +- sql/sql_yacc.yy | 5 +++ 6 files changed, 191 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index e51dc113f97..87aa4b98d81 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -720,3 +720,43 @@ Warning 1292 Truncated incorrect datetime value: '2005-01-00' select time_format('100:00:00', '%H %k %h %I %l'); time_format('100:00:00', '%H %k %h %I %l') 100 100 04 04 4 +create table t1 (a timestamp default '2005-05-05 01:01:01', +b timestamp default '2005-05-05 01:01:01'); +create function t_slow_sysdate() returns timestamp +begin +do sleep(2); +return sysdate(); +end; +// +insert into t1 set a = sysdate(), b = t_slow_sysdate();// +create trigger t_before before insert on t1 +for each row begin +set new.b = t_slow_sysdate(); +end +// +insert into t1 set a = sysdate(); +select a != b from t1; +a != b +1 +1 +drop trigger t_before; +drop function t_slow_sysdate; +drop table t1; +create table t1 (a datetime, i int, b datetime); +insert into t1 select sysdate(), sleep(1), sysdate() from dual; +select a != b from t1; +a != b +1 +drop table t1; +create procedure t_sysdate() +begin +select sysdate() into @a; +do sleep(2); +select sysdate() into @b; +select @a != @b; +end; +// +call t_sysdate(); +@a != @b +1 +drop procedure t_sysdate; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 0538e6111b9..3dd7f7276fb 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -353,3 +353,55 @@ select last_day('2005-01-00'); # the 0-11 range # select time_format('100:00:00', '%H %k %h %I %l'); + +# +# Bug #12562: Make SYSDATE behave like it does in Oracle: always the current +# time, regardless of magic to make NOW() always the same for the +# entirety of a statement. +create table t1 (a timestamp default '2005-05-05 01:01:01', + b timestamp default '2005-05-05 01:01:01'); +delimiter //; +create function t_slow_sysdate() returns timestamp +begin + do sleep(2); + return sysdate(); +end; +// + +insert into t1 set a = sysdate(), b = t_slow_sysdate();// + +create trigger t_before before insert on t1 +for each row begin + set new.b = t_slow_sysdate(); +end +// + +delimiter ;// + +insert into t1 set a = sysdate(); + +select a != b from t1; + +drop trigger t_before; +drop function t_slow_sysdate; +drop table t1; + +create table t1 (a datetime, i int, b datetime); +insert into t1 select sysdate(), sleep(1), sysdate() from dual; +select a != b from t1; +drop table t1; + +delimiter //; +create procedure t_sysdate() +begin + select sysdate() into @a; + do sleep(2); + select sysdate() into @b; + select @a != @b; +end; +// +delimiter ;// +call t_sysdate(); +drop procedure t_sysdate; + +# End of 5.0 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index dfbfca3b078..0d9e23ff0a1 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1476,9 +1476,9 @@ void Item_func_now_utc::store_now_in_TIME(TIME *now_time) bool Item_func_now::get_date(TIME *res, - uint fuzzy_date __attribute__((unused))) + uint fuzzy_date __attribute__((unused))) { - *res=ltime; + *res= ltime; return 0; } @@ -1491,6 +1491,70 @@ int Item_func_now::save_in_field(Field *to, bool no_conversions) } +/* + Converts current time in my_time_t to TIME represenatation for local + time zone. Defines time zone (local) used for whole SYSDATE function. +*/ +void Item_func_sysdate_local::store_now_in_TIME(TIME *now_time) +{ + THD *thd= current_thd; + thd->variables.time_zone->gmt_sec_to_TIME(now_time, time(NULL)); + thd->time_zone_used= 1; +} + + +String *Item_func_sysdate_local::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + store_now_in_TIME(<ime); + buff_length= (uint) my_datetime_to_str(<ime, buff); + str_value.set(buff, buff_length, &my_charset_bin); + return &str_value; +} + + +longlong Item_func_sysdate_local::val_int() +{ + DBUG_ASSERT(fixed == 1); + store_now_in_TIME(<ime); + return (longlong) TIME_to_ulonglong_datetime(<ime); +} + + +double Item_func_sysdate_local::val_real() +{ + DBUG_ASSERT(fixed == 1); + store_now_in_TIME(<ime); + return (longlong) TIME_to_ulonglong_datetime(<ime); +} + + +void Item_func_sysdate_local::fix_length_and_dec() +{ + decimals= 0; + collation.set(&my_charset_bin); + max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; +} + + +bool Item_func_sysdate_local::get_date(TIME *res, + uint fuzzy_date __attribute__((unused))) +{ + store_now_in_TIME(<ime); + *res= ltime; + return 0; +} + + +int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions) +{ + store_now_in_TIME(<ime); + to->set_notnull(); + to->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); + return 0; +} + + String *Item_func_sec_to_time::val_str(String *str) { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index d9300451fe7..4602088a5f5 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -446,6 +446,7 @@ public: class Item_func_now :public Item_date_func { +protected: longlong value; char buff[20*2+32]; // +32 to make my_snprintf_{8bit|ucs2} happy uint buff_length; @@ -485,6 +486,32 @@ public: }; +/* + This is like NOW(), but always uses the real current time, not the + query_start(). This matches the Oracle behavior. +*/ +class Item_func_sysdate_local :public Item_func_now +{ +public: + Item_func_sysdate_local() :Item_func_now() {} + Item_func_sysdate_local(Item *a) :Item_func_now(a) {} + bool const_item() const { return 0; } + const char *func_name() const { return "sysdate"; } + void store_now_in_TIME(TIME *now_time); + double val_real(); + longlong val_int(); + int save_in_field(Field *to, bool no_conversions); + String *val_str(String *str); + void fix_length_and_dec(); + bool get_date(TIME *res, uint fuzzy_date); + void update_used_tables() + { + Item_func_now::update_used_tables(); + used_tables_cache|= RAND_TABLE_BIT; + } +}; + + class Item_func_from_days :public Item_date { public: diff --git a/sql/lex.h b/sql/lex.h index 7b6d86e327e..4bf3671e5be 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -751,7 +751,7 @@ static SYMBOL sql_functions[] = { { "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)}, { "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)}, { "SUM", SYM(SUM_SYM)}, - { "SYSDATE", SYM(NOW_SYM)}, + { "SYSDATE", SYM(SYSDATE)}, { "SYSTEM_USER", SYM(USER)}, { "TAN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)}, { "TIME_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b446a06ded1..6b447396dec 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -580,6 +580,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SUM_SYM %token SUPER_SYM %token SUSPEND_SYM +%token SYSDATE %token TABLES %token TABLESPACE %token TABLE_SYM @@ -4683,6 +4684,10 @@ simple_expr: { $$= new Item_func_substr($3,$5); } | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' { $$= new Item_func_substr_index($3,$5,$7); } + | SYSDATE optional_braces + { $$= new Item_func_sysdate_local(); Lex->safe_to_cache_query=0;} + | SYSDATE '(' expr ')' + { $$= new Item_func_sysdate_local($3); Lex->safe_to_cache_query=0;} | TIME_SYM '(' expr ')' { $$= new Item_time_typecast($3); } | TIMESTAMP '(' expr ')' From 681a4a3a2467a706ca677bbf52712dfee1c952e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 01:02:40 +0200 Subject: [PATCH 68/80] ha_tina.cc: Some lack madvice() sql/examples/ha_tina.cc: Some lack madvice() --- sql/examples/ha_tina.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc index 1e2751f3016..26cd3d2a07e 100644 --- a/sql/examples/ha_tina.cc +++ b/sql/examples/ha_tina.cc @@ -650,7 +650,9 @@ int ha_tina::rnd_init(bool scan) current_position= next_position= 0; records= 0; chain_ptr= chain; +#ifdef MADV_SEQUENTIAL (void)madvise(share->mapped_file,share->file_stat.st_size,MADV_SEQUENTIAL); +#endif DBUG_RETURN(0); } From ae450d8aba9e6a70c7c11ba272fec7dd05a83a7b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Aug 2005 17:08:55 -0700 Subject: [PATCH 69/80] Fix for building without --without-server, which was broken by fix for building with --without-server. configure.in: Re-add mysys to sql_server_dirs, so it is built before dbug. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 093ad166ff5..a661e73df56 100644 --- a/configure.in +++ b/configure.in @@ -2487,7 +2487,7 @@ then THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o" AC_SUBST(THREAD_LOBJECTS) server_scripts="mysqld_safe mysql_install_db" - sql_server_dirs="strings dbug extra regex" + sql_server_dirs="strings mysys dbug extra regex" # From 0154ae5443f272ea0915ec47581167f6aa37cb15 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 02:27:52 +0200 Subject: [PATCH 70/80] disabled.def: Disabled unstable tests, bugs filed mysql-test/t/disabled.def: Disabled unstable tests, bugs filed --- mysql-test/t/disabled.def | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 60543fe55f9..fe95a543fb5 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,5 +10,8 @@ # ############################################################################## -sp-goto:GOTO is currently is disabled - will be fixed in the future - +sp-goto : GOTO is currently is disabled - will be fixed in the future +rpl_relayrotate : Unstable test case, bug#12429 +rpl_until : Unstable test case, bug#12429 +rpl_deadlock : Unstable test case, bug#12429 +kill : Unstable test case, bug#9712 From 5baa13ce126763bb66254b52b459bc37e701fa01 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 09:38:06 +0300 Subject: [PATCH 71/80] After merge fixes mysql-test/r/subselect2.result: After merge fix sql/handler.cc: Remove compiler warning sql/sql_acl.cc: After merge fix sql/sql_db.cc: After merge fix --- mysql-test/r/subselect2.result | 2 +- sql/handler.cc | 2 +- sql/sql_acl.cc | 17 ++++++++++------- sql/sql_db.cc | 6 +++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index 4488af8206c..bc902ea7b0f 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -121,8 +121,8 @@ c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff1744455354420 EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion'; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 9 Using where +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 34 test.t2.DOCID 1 1 PRIMARY t4 eq_ref PRIMARY PRIMARY 34 test.t2.DOCTYPEID 1 -1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1 2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where 3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where 4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where diff --git a/sql/handler.cc b/sql/handler.cc index 0b247f83af1..cf1fbfec465 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1023,7 +1023,7 @@ bool mysql_xa_recover(THD *thd) DBUG_RETURN(1); pthread_mutex_lock(&LOCK_xid_cache); - while (xs=(XID_STATE*)hash_element(&xid_cache, i++)) + while ((xs= (XID_STATE*)hash_element(&xid_cache, i++))) { if (xs->xa_state==XA_PREPARED) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 13d84129d8e..4629752c6a7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2494,7 +2494,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, The following should always succeed as new users are created before this function is called! */ - if (!find_acl_user(combo.host.str,combo.user.str)) + if (!find_acl_user(combo.host.str, combo.user.str, FALSE)) { my_error(ER_PASSWORD_NO_MATCH,MYF(0)); DBUG_RETURN(-1); @@ -4611,11 +4611,12 @@ static int handle_grant_struct(uint struct_no, bool drop, ACL_DB *acl_db; GRANT_NAME *grant_name; DBUG_ENTER("handle_grant_struct"); + DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'", + struct_no, user_from->user.str, user_from->host.str)); + LINT_INIT(acl_user); LINT_INIT(acl_db); LINT_INIT(grant_name); - 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) { @@ -5311,10 +5312,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, combo->user.str= thd->user; - if (!find_acl_user(combo->host.str=(char*)thd->host_or_ip, combo->user.str) && - !find_acl_user(combo->host.str=(char*)thd->host, combo->user.str) && - !find_acl_user(combo->host.str=(char*)thd->ip, combo->user.str) && - !find_acl_user(combo->host.str=(char*)"%", combo->user.str)) + if (!find_acl_user(combo->host.str=(char*)thd->host_or_ip, combo->user.str, + FALSE) && + !find_acl_user(combo->host.str=(char*)thd->host, combo->user.str, + FALSE) && + !find_acl_user(combo->host.str=(char*)thd->ip, combo->user.str, FALSE) && + !find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE)) DBUG_RETURN(TRUE); bzero((char*)tables, sizeof(TABLE_LIST)); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 27f20753475..5ca3f07f0bd 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -706,14 +706,14 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) query_end= query + MAX_DROP_TABLE_Q_LEN; db_len= strlen(db); - for (tbl= dropped_tables; tbl; tbl= tbl->next) + for (tbl= dropped_tables; tbl; tbl= tbl->next_local) { uint tbl_name_len; if (!tbl->was_dropped) continue; /* 3 for the quotes and the comma*/ - tbl_name_len= strlen(tbl->real_name) + 3; + tbl_name_len= strlen(tbl->table_name) + 3; if (query_pos + tbl_name_len + 1 >= query_end) { write_to_binlog(thd, query, query_pos -1 - query, db, db_len); @@ -721,7 +721,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } *query_pos++ = '`'; - query_pos= strmov(query_pos,tbl->real_name); + query_pos= strmov(query_pos,tbl->table_name); *query_pos++ = '`'; *query_pos++ = ','; } From 750a05887f00153f1dd3556493ddbf794d7fdd20 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 09:24:21 +0200 Subject: [PATCH 72/80] fix for bug #12533 (crash on DESCRIBE after renaming base table column) mysql-test/r/view.result: result of test for bug #12533 mysql-test/t/view.test: test for bug #12533 (crash on DESCRIBE after renaming base table column) sql/sql_show.cc: close thread tables even if process_table bails out --- mysql-test/r/view.result | 12 ++++++++++++ mysql-test/t/view.test | 17 +++++++++++++++++ sql/sql_show.cc | 17 ++++++++++------- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f56c6558e4f..4767ca0eca7 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2115,3 +2115,15 @@ CREATE VIEW v1 AS SELECT f1(); ERROR HY000: View's SELECT refers to a temporary table 't1' DROP FUNCTION f1; DROP TABLE t1; +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +CREATE TABLE t1 (f4 CHAR(5)); +CREATE VIEW v1 AS SELECT * FROM t1; +DESCRIBE v1; +Field Type Null Key Default Extra +f4 char(5) YES NULL +ALTER TABLE t1 CHANGE COLUMN f4 f4x CHAR(5); +DESCRIBE v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +DROP TABLE t1; +DROP VIEW v1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a5b72a16972..4c11f93e683 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1966,3 +1966,20 @@ CREATE VIEW v1 AS SELECT f1(); DROP FUNCTION f1; DROP TABLE t1; +# +# BUG #12533 (crash on DESCRIBE after renaming base table column) +# +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +--enable_warnings + +CREATE TABLE t1 (f4 CHAR(5)); +CREATE VIEW v1 AS SELECT * FROM t1; +DESCRIBE v1; + +ALTER TABLE t1 CHANGE COLUMN f4 f4x CHAR(5); +--error 1356 +DESCRIBE v1; +DROP TABLE t1; +DROP VIEW v1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3bb349d7c29..7e7771c5b37 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1985,13 +1985,15 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) lex->all_selects_list= lsel; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); - if (schema_table->process_table(thd, show_table_list, + /* + get_all_tables() returns 1 on failure and 0 on success thus + return only these and not the result code of ::process_table() + */ + error= test(schema_table->process_table(thd, show_table_list, table, res, show_table_list->db, - show_table_list->alias)) - goto err; + show_table_list->alias)); close_thread_tables(thd); show_table_list->table= 0; - error= 0; goto err; } @@ -2090,11 +2092,12 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) lex->derived_tables= 0; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); - if (schema_table->process_table(thd, show_table_list, table, + res= schema_table->process_table(thd, show_table_list, table, res, base_name, - show_table_list->alias)) - goto err; + show_table_list->alias); close_thread_tables(thd); + if (res) + goto err; } } } From 8bd9992e49feef4033ab128eb3e09379be144298 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 12:03:19 +0300 Subject: [PATCH 73/80] Make test predictable mysql-test/r/information_schema.result: Ensure that rows are in given order mysql-test/t/information_schema.test: Ensure that rows are in given order --- mysql-test/r/information_schema.result | 4 ++-- mysql-test/t/information_schema.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 91a99e4ea55..6d8907fff00 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -273,10 +273,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE # ALL NULL NULL NULL NULL 2 1 SIMPLE # ALL NULL NULL NULL NULL 2 Using where select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, -mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8); +mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1; ROUTINE_NAME name -sub1 sub1 sel2 sel2 +sub1 sub1 select count(*) from information_schema.ROUTINES; count(*) 2 diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index d6a47b88ac0..23f88b75576 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -138,7 +138,7 @@ information_schema.SCHEMATA b where a.ROUTINE_SCHEMA = b.SCHEMA_NAME; select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, -mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8); +mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1; select count(*) from information_schema.ROUTINES; connect (user1,localhost,mysqltest_1,,); From 00b9916aff20d67f8441762e69cec47cffab9c9a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 11:17:54 +0200 Subject: [PATCH 74/80] Correct a typing error: Missing ".pl" suffix is essential. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 5900d709dcf..a34b3b7099f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -101,7 +101,7 @@ tags: test: cd mysql-test; \ - perl ./mysql-test-run && perl ./mysql-test-run --ps-protocol + perl ./mysql-test-run.pl && perl ./mysql-test-run.pl --ps-protocol test-force: cd mysql-test; \ From 7887d8b808b4938e1d3673824afb4c4604018274 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 13:15:29 +0200 Subject: [PATCH 75/80] config: updated tomas default checkout BitKeeper/etc/config: updated tomas default checkout --- BitKeeper/etc/config | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index d9c45d3d36a..81e867e514f 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -72,5 +72,6 @@ hours: [kostja:]checkout:get [nick:]checkout:get [jonas:]checkout:get +[tomas:]checkout:get checkout:edit eoln:unix From 58e57625c45ad7deb2deb648786b41781f1e589f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 13:16:29 +0200 Subject: [PATCH 76/80] bug#12027 - ndb When detecting corrupt schema file. Make sure to close it (as it will be opened later when rewriting a clean copy) ndb/src/kernel/blocks/dbdict/Dbdict.cpp: bug#12027 When detecting corrupt schema file. Make sure to close it (as it will be opened later when rewriting a clean copy) --- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index f60720a1345..5ad225f3f37 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -369,6 +369,9 @@ void Dbdict::execFSCLOSECONF(Signal* signal) jam(); closeWriteTableConf(signal, fsPtr); break; + case FsConnectRecord::FsConnectRecord::OPEN_READ_SCHEMA2: + openSchemaFile(signal, 1, fsPtr.i, false); + break; default: jamLine((fsPtr.p->fsState & 0xFFF)); ndbrequire(false); @@ -1012,10 +1015,13 @@ void Dbdict::readSchemaConf(Signal* signal, void Dbdict::readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr) { + /** + * First close corrupt file + */ fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2; - openSchemaFile(signal, 1, fsPtr.i, false); + closeFile(signal, fsPtr.p->filePtr, fsPtr.i); return; -}//Dbdict::readSchemaRef() +} void Dbdict::closeReadSchemaConf(Signal* signal, FsConnectRecordPtr fsPtr) From d29df5645bf0cdac2ff08a7da305e62edcd79604 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 15:34:14 +0400 Subject: [PATCH 77/80] Fix Bug#11333 "Stored Procedure: Memory blow up on repeated SELECT ... INTO query" mysql-test/r/sp.result: update result mysql-test/t/sp.test: Add test for Bug #11333 "Stored Procedure: Memory blow up on repeated SELECT ... INTO query" sql/item.cc: we should call destructors for Items before reuse sql/item.h: Add new method and constructor for Item_string. sql/sp_head.cc: String allocation should be done on the system heap for now. --- mysql-test/r/sp.result | 19 +++++++++++++++++++ mysql-test/t/sp.test | 34 ++++++++++++++++++++++++++++++++++ sql/item.cc | 1 + sql/item.h | 18 ++++++++++++++++++ sql/sp_head.cc | 23 +++++++++++++++++++---- 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d1d41035475..1570f2252ec 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3166,4 +3166,23 @@ a 4 truncate t2| drop procedure if exists bug12168| +drop table if exists t3| +drop procedure if exists bug11333| +create table t3 (c1 char(128))| +insert into t3 values +('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')| +create procedure bug11333(i int) +begin +declare tmp varchar(128); +set @x = 0; +repeat +select c1 into tmp from t3 +where c1 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; +set @x = @x + 1; +until @x >= i +end repeat; +end| +call bug11333(10)| +drop procedure bug11333| +drop table t3| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f3e7c3e07a0..6f79243a2b1 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3995,6 +3995,40 @@ select * from t2| truncate t2| drop procedure if exists bug12168| +# +# Bug #11333 "Stored Procedure: Memory blow up on repeated SELECT ... INTO +# query" +# One more memleak bug. Use the test to check memory consumption. +# + +--disable_warnings +drop table if exists t3| +drop procedure if exists bug11333| +--enable_warnings + +create table t3 (c1 char(128))| + +insert into t3 values + ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')| + + +create procedure bug11333(i int) +begin + declare tmp varchar(128); + set @x = 0; + repeat + select c1 into tmp from t3 + where c1 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; + set @x = @x + 1; + until @x >= i + end repeat; +end| + +call bug11333(10)| + +drop procedure bug11333| +drop table t3| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/item.cc b/sql/item.cc index 7575a6a218b..98caf4918ab 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -303,6 +303,7 @@ void *Item::operator new(size_t size, Item *reuse, uint *rsize) if (rsize) (*rsize)= reuse->rsize; reuse->cleanup(); + delete reuse; TRASH((void *)reuse, size); return (void *)reuse; } diff --git a/sql/item.h b/sql/item.h index 4dfd99e0dbd..51f7c641de1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1298,6 +1298,15 @@ public: // it is constant => can be used without fix_fields (and frequently used) fixed= 1; } + /* Just create an item and do not fill string representation */ + Item_string(CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) + { + collation.set(cs, dv); + max_length= 0; + set_name(NULL, 0, cs); + decimals= NOT_FIXED_DEC; + fixed= 1; + } Item_string(const char *name_par, const char *str, uint length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { @@ -1309,6 +1318,15 @@ public: // it is constant => can be used without fix_fields (and frequently used) fixed= 1; } + /* + This is used in stored procedures to avoid memory leaks and + does a deep copy of its argument. + */ + void set_str_with_copy(const char *str_arg, uint length_arg) + { + str_value.copy(str_arg, length_arg, collation.collation); + max_length= str_value.numchars() * collation.collation->mbmaxlen; + } enum Type type() const { return STRING_ITEM; } double val_real(); longlong val_int(); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f119ef1ec22..0a3521e8855 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -249,10 +249,25 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, DBUG_PRINT("info",("default result: %*s", s->length(), s->c_ptr_quick())); CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) - Item_string(thd->strmake(s->ptr(), - s->length()), s->length(), - it->collation.collation), - use_callers_arena, &backup_current_arena); + Item_string(it->collation.collation), + use_callers_arena, &backup_current_arena); + /* + We have to use special constructor and allocate string + on system heap here. This is because usual Item_string + constructor would allocate memory in the callers arena. + This would lead to the memory leak in SP loops. + See Bug #11333 "Stored Procedure: Memory blow up on + repeated SELECT ... INTO query" for sample of such SP. + TODO: Usage of the system heap gives significant overhead, + however usual "reuse" mechanism does not work here, as + Item_string has no max size. That is, if we have a loop, which + has string variable with constantly increasing size, we would have + to allocate new pieces of memory again and again on each iteration. + In future we should probably reserve some area of memory for + not-very-large strings and reuse it. But for large strings + we would have to use system heap anyway. + */ + ((Item_string*) it)->set_str_with_copy(s->ptr(), s->length()); } break; } From 8a5e527453eebea99854f7b8f8faee364f620a11 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 17:34:34 +0400 Subject: [PATCH 78/80] Fix for BUG#12335 (SP replication) : New binlogging strategy for stored PROCEDUREs/FUNCTIONs. "Interleaved SPs execution is now binlogged properly, "SELECT spfunc()" is binlogged too. The known remaining issue is binlogging/replication of "a routine is deleted while it is executed" scenario. mysql-test/r/rpl_sp.result: Fix for BUG#12335: updated test cases/results mysql-test/t/rpl_sp.test: Fix for BUG#12335: updated test cases/results sql/item.cc: Fix for BUG#12335 (SP replication): - Added Item_name_const 'function' - Addede 'delete reuse' to call dtor on item reuse sql/item.h: Fix for BUG#12335 (SP replication) : Added Item_name_const 'function' + code cleanup sql/item_create.cc: Fix for BUG#12335 (SP replication) : Added Item_name_const 'function' sql/item_create.h: Fix for BUG#12335 (SP replication) : Added Item_name_const 'function' sql/item_func.cc: Fix for BUG#12335 (SP replication) : binary log is now constrolled from within execute_function. sql/lex.h: Fix for BUG#12335 (SP replication) : Added Item_name_const 'function' sql/log.cc: Fix for BUG#12335 (SP replication) : Added MYSQL_LOG::{start|stop}_union_events to allow one to temporary disable binlogging but collect a 'union' information about binlog write calls. sql/mysql_priv.h: Fix for BUG#12335 (SP replication) sql/sp_head.cc: Fix for BUG#12335 (SP replication) : Now we use different SP binlogging strategy, grep for StoredRoutinesBinlogging for details sql/sp_head.h: Comments added sql/sp_pcontext.h: Comments added sql/sp_rcontext.h: Comments added sql/sql_class.cc: Fix for BUG#12335 (SP replication) : Now we use different SP binlogging strategy, grep for StoredRoutinesBinlogging for details sql/sql_class.h: Fix for BUG#12335 (SP replication) : Added MYSQL_LOG::{start|stop}_union_events to allow one to temporary disable binlogging but collect a 'union' information about binlog write calls. sql/sql_delete.cc: Fix for BUG#12335: check THD::query_str_binlog_unsuitable when writing to binlog. sql/sql_insert.cc: Fix for BUG#12335: check THD::query_str_binlog_unsuitable when writing to binlog. sql/sql_lex.cc: Fix for BUG#12335 (SP replication): Add ability to extract previous returned token from the tokenizer. sql/sql_lex.h: Fix for BUG#12335 (SP replication): Add ability to extract previous returned token from the tokenizer. sql/sql_parse.cc: Fix for BUG#12335 (SP replication) : Now we use different SP binlogging strategy, grep for StoredRoutinesBinlogging for details sql/sql_update.cc: Fix for BUG#12335: check THD::query_str_binlog_unsuitable when writing to binlog. sql/sql_yacc.yy: Fix for BUG#12335 (SP replication) : When creating Item_splocal, remember where it is located in the query. --- mysql-test/r/rpl_sp.result | 19 +- mysql-test/r/rpl_sp_effects.result | 216 +++++++++++++++++++++ mysql-test/t/rpl_sp.test | 4 +- mysql-test/t/rpl_sp_effects-master.opt | 1 + mysql-test/t/rpl_sp_effects-slave.opt | 1 + mysql-test/t/rpl_sp_effects.test | 234 +++++++++++++++++++++++ sql/item.cc | 105 ++++++++++- sql/item.h | 100 ++++++++-- sql/item_create.cc | 5 + sql/item_create.h | 1 + sql/item_func.cc | 8 +- sql/lex.h | 1 + sql/log.cc | 21 +++ sql/mysql_priv.h | 1 + sql/sp_head.cc | 252 ++++++++++++++++++++++++- sql/sp_head.h | 23 ++- sql/sp_pcontext.h | 5 + sql/sp_rcontext.h | 10 + sql/sql_array.h | 69 +++++++ sql/sql_class.cc | 6 +- sql/sql_class.h | 44 ++++- sql/sql_delete.cc | 6 +- sql/sql_insert.cc | 3 +- sql/sql_lex.cc | 4 + sql/sql_lex.h | 4 + sql/sql_parse.cc | 37 ++-- sql/sql_update.cc | 6 +- sql/sql_yacc.yy | 9 +- 28 files changed, 1118 insertions(+), 77 deletions(-) create mode 100644 mysql-test/r/rpl_sp_effects.result create mode 100644 mysql-test/t/rpl_sp_effects-master.opt create mode 100644 mysql-test/t/rpl_sp_effects-slave.opt create mode 100644 mysql-test/t/rpl_sp_effects.test create mode 100644 sql/sql_array.h diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index b31951e93c5..394f93f2ea0 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -60,7 +60,8 @@ set b = 8; insert into t1 values (b); insert into t1 values (unix_timestamp()); end -master-bin.000001 # Query 1 # use `mysqltest1`; call foo() +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8)) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp()) select * from t1; a 8 @@ -76,8 +77,10 @@ reads sql data select * from mysqltest1.t1; call foo2(); a -show binlog events from 605; +show binlog events from 518; Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8)) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp()) master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2() not deterministic @@ -124,7 +127,7 @@ alter procedure foo4 sql security invoker; call foo4(); show warnings; Level Code Message -show binlog events from 841; +show binlog events from 990; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int) @@ -141,9 +144,12 @@ begin insert into t2 values(3); insert into t1 values (5); end -master-bin.000001 # Query 1 # use `mysqltest1`; call foo3() +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (15) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo4 sql security invoker -master-bin.000001 # Query 1 # use `mysqltest1`; call foo4() +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5) select * from t1; a 15 @@ -160,6 +166,8 @@ a select * from t2; a 3 +3 +3 select * from mysql.proc where name="foo4" and db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES INVOKER begin @@ -196,6 +204,7 @@ a select * from t1; a 21 +20 select * from t2; a 23 diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result new file mode 100644 index 00000000000..738fd08450a --- /dev/null +++ b/mysql-test/r/rpl_sp_effects.result @@ -0,0 +1,216 @@ +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; +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; +drop table if exists t1,t2; +drop view if exists v1; +create table t1 (a int); +create procedure p1() +begin +declare spv int default 0; +while spv < 5 do +insert into t1 values(spv+1); +set spv=spv+1; +end while; +end// +call p1(); +select * from t1; +a +1 +2 +3 +4 +5 +delete from t1; +create procedure p2() +begin +declare a int default 4; +create table t2 as select a; +end// +call p2(); +select * from t2; +a +4 +select * from t2; +a +4 +drop procedure p1; +drop procedure p2; +drop table t2; +create function f1(x int) returns int +begin +insert into t1 values(x); +return x+1; +end// +create procedure p1(a int, b int) +begin +declare v int default f1(5); +if (f1(6)) then +select 'yes'; +end if; +set v = f1(7); +while f1(8) < 1 do +select 'this cant be'; +end while; +end// +call p1(f1(1), f1(2)); +yes +yes +select * from t1; +a +1 +2 +5 +6 +7 +8 +create table t2(a int); +insert into t2 values (10),(11); +select a,f1(a) from t2; +a f1(a) +10 11 +11 12 +insert into t2 select f1(3); +select 'master:',a from t1; +master: a +master: 1 +master: 2 +master: 5 +master: 6 +master: 7 +master: 8 +master: 10 +master: 11 +master: 3 +select 'slave:',a from t1; +slave: a +slave: 1 +slave: 2 +slave: 5 +slave: 6 +slave: 7 +slave: 8 +slave: 10 +slave: 11 +slave: 3 +drop procedure p1; +delete from t1; +delete from t2; +delete from t1; +insert into t2 values(1),(2); +create view v1 as select f1(a) from t2; +select * from v1; +f1(a) +2 +3 +select 'master:',a from t1; +master: a +master: 1 +master: 2 +select 'slave:',a from t1; +slave: a +slave: 1 +slave: 2 +drop view v1; +delete from t1; +prepare s1 from 'select f1(?)'; +set @xx=123; +execute s1 using @xx; +f1(?) +124 +select 'master:',a from t1; +master: a +master: 123 +select 'slave:',a from t1; +slave: a +slave: 123 +delete from t1; +create procedure p1(spv int) +begin +declare c cursor for select f1(spv) from t2; +while (spv > 2) do +open c; +fetch c into spv; +close c; +set spv= spv - 10; +end while; +end// +call p1(15); +select 'master:',a from t1; +master: a +master: 15 +master: 15 +master: 6 +master: 6 +select 'slave:',a from t1; +slave: a +slave: 15 +slave: 15 +slave: 6 +slave: 6 +drop procedure p1; +drop function f1; +drop table t1,t2; +create table t1 (a int); +create table t2 (a char(200)); +create procedure p1() +begin +declare dummy int; +while ((select count(*) from t1) < 1) do +set dummy = sleep(1); +end while; +end// +create procedure p2() +begin +select f1(); +call p1(); +delete from t1 limit 1; +select f1(); +call p1(); +delete from t1 limit 1; +select f1(); +end// +create function f1() returns int +begin +insert into t2 values('f1-r1'); +return 0; +end// + call p2(); +drop function f1// +create function f1() returns int +begin +insert into t2 values('f1-r2'); +return 0; +end// +insert into t1 values (1) // +call p1()// +drop function f1// +create function f1() returns int +begin +insert into t2 values('f1-r3'); +return 0; +end// +insert into t1 values (1) // +call p1()// +f1() +0 +f1() +0 +f1() +0 +select * from t2; +a +f1-r1 +f1-r1 +f1-r1 +select * from t2; +a +f1-r1 +f1-r3 +f1-r3 +drop table t1; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index 184ac4edea1..98a06159a57 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -83,7 +83,7 @@ create procedure foo2() call foo2(); # verify CALL is not in binlog --replace_column 2 # 5 # -show binlog events from 605; +show binlog events from 518; --error 1418; alter procedure foo2 contains sql; @@ -147,7 +147,7 @@ show warnings; # Check that only successful CALLs are in binlog --replace_column 2 # 5 # -show binlog events from 841; +show binlog events from 990; # Note that half-failed CALLs are not in binlog, which is a known # bug. If we compare t2 on master and slave we see they differ: diff --git a/mysql-test/t/rpl_sp_effects-master.opt b/mysql-test/t/rpl_sp_effects-master.opt new file mode 100644 index 00000000000..61dd7a6ad0e --- /dev/null +++ b/mysql-test/t/rpl_sp_effects-master.opt @@ -0,0 +1 @@ +--log_bin_trust_routine_creators=1 diff --git a/mysql-test/t/rpl_sp_effects-slave.opt b/mysql-test/t/rpl_sp_effects-slave.opt new file mode 100644 index 00000000000..61dd7a6ad0e --- /dev/null +++ b/mysql-test/t/rpl_sp_effects-slave.opt @@ -0,0 +1 @@ +--log_bin_trust_routine_creators=1 diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test new file mode 100644 index 00000000000..825fd764f4d --- /dev/null +++ b/mysql-test/t/rpl_sp_effects.test @@ -0,0 +1,234 @@ +# Test of replication of stored procedures (WL#2146 for MySQL 5.0) + +source include/master-slave.inc; + +# **************************************************************** +connection master; + +# cleanup +--disable_warnings +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; +drop table if exists t1,t2; +drop view if exists v1; +--enable_warnings +create table t1 (a int); + +# 1. Test simple variables use. +delimiter //; +create procedure p1() +begin + declare spv int default 0; + while spv < 5 do + insert into t1 values(spv+1); + set spv=spv+1; + end while; +end// +delimiter ;// + +call p1(); + +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +delete from t1; + +# 2. Test SP variable name +delimiter //; +create procedure p2() +begin + declare a int default 4; + create table t2 as select a; +end// +delimiter ;// + +call p2(); +select * from t2; +sync_slave_with_master; +connection slave; +select * from t2; + +connection master; +drop procedure p1; +drop procedure p2; +drop table t2; + +# 3. Test FUNCTIONs in various places + +delimiter //; +create function f1(x int) returns int +begin + insert into t1 values(x); + return x+1; +end// + +create procedure p1(a int, b int) +begin + declare v int default f1(5); + if (f1(6)) then + select 'yes'; + end if; + set v = f1(7); + while f1(8) < 1 do + select 'this cant be'; + end while; + +end// +delimiter ;// + +call p1(f1(1), f1(2)); +select * from t1; + +create table t2(a int); +insert into t2 values (10),(11); +select a,f1(a) from t2; + +# This shouldn't put separate 'call f1(3)' into binlog: +insert into t2 select f1(3); +select 'master:',a from t1; + +sync_slave_with_master; +connection slave; +select 'slave:',a from t1; + +connection master; +drop procedure p1; +delete from t1; +delete from t2; + +# 4. VIEWs +delete from t1; +insert into t2 values(1),(2); +create view v1 as select f1(a) from t2; +select * from v1; +select 'master:',a from t1; + +sync_slave_with_master; +connection slave; +select 'slave:',a from t1; + +connection master; +drop view v1; +delete from t1; + +# 5. Prepared statements. +prepare s1 from 'select f1(?)'; +set @xx=123; +execute s1 using @xx; +select 'master:',a from t1; + +sync_slave_with_master; +connection slave; +select 'slave:',a from t1; + +connection master; +delete from t1; + +# 5. Cursors. +# t2 has (1),(2); +delimiter //; +create procedure p1(spv int) +begin + declare c cursor for select f1(spv) from t2; + while (spv > 2) do + open c; + fetch c into spv; + close c; + set spv= spv - 10; + end while; +end// +delimiter ;// + +call p1(15); +select 'master:',a from t1; +sync_slave_with_master; +connection slave; +select 'slave:',a from t1; + +connection master; +drop procedure p1; +drop function f1; +drop table t1,t2; + +sync_slave_with_master; + +# The following will produce incorrect results: +connection master; +create table t1 (a int); +create table t2 (a char(200)); + +delimiter //; +create procedure p1() +begin + declare dummy int; + while ((select count(*) from t1) < 1) do + set dummy = sleep(1); + end while; +end// + +create procedure p2() +begin + select f1(); + + call p1(); + delete from t1 limit 1; + + select f1(); + + call p1(); + delete from t1 limit 1; + + select f1(); +end// + +create function f1() returns int +begin + insert into t2 values('f1-r1'); + return 0; +end// +delimiter ;// + +connection master; +send call p2(); + +connection master1; +delimiter //; + +drop function f1// +create function f1() returns int +begin + insert into t2 values('f1-r2'); + return 0; +end// +insert into t1 values (1) // + +call p1()// + +drop function f1// +create function f1() returns int +begin + insert into t2 values('f1-r3'); + return 0; +end// +insert into t1 values (1) // + +call p1()// + +delimiter ;// + +connection master; +reap; + +select * from t2; + +connection slave; +select * from t2; + +# Clean up +connection master; +drop table t1; + +sync_slave_with_master; + diff --git a/sql/item.cc b/sql/item.cc index d8f5a7cf9c4..41f49b5d000 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -303,6 +303,7 @@ void *Item::operator new(size_t size, Item *reuse, uint *rsize) if (rsize) (*rsize)= reuse->rsize; reuse->cleanup(); + delete reuse; TRASH((void *)reuse, size); return (void *)reuse; } @@ -789,12 +790,15 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) } +/***************************************************************************** + Item_splocal methods +*****************************************************************************/ double Item_splocal::val_real() { DBUG_ASSERT(fixed); Item *it= this_item(); double ret= it->val_real(); - Item::null_value= it->null_value; + null_value= it->null_value; return ret; } @@ -804,7 +808,7 @@ longlong Item_splocal::val_int() DBUG_ASSERT(fixed); Item *it= this_item(); longlong ret= it->val_int(); - Item::null_value= it->null_value; + null_value= it->null_value; return ret; } @@ -814,7 +818,7 @@ String *Item_splocal::val_str(String *sp) DBUG_ASSERT(fixed); Item *it= this_item(); String *ret= it->val_str(sp); - Item::null_value= it->null_value; + null_value= it->null_value; return ret; } @@ -824,7 +828,7 @@ my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value) DBUG_ASSERT(fixed); Item *it= this_item(); my_decimal *val= it->val_decimal(decimal_value); - Item::null_value= it->null_value; + null_value= it->null_value; return val; } @@ -833,7 +837,7 @@ bool Item_splocal::is_null() { Item *it= this_item(); bool ret= it->is_null(); - Item::null_value= it->null_value; + null_value= it->null_value; return ret; } @@ -898,6 +902,97 @@ void Item_splocal::print(String *str) } +/***************************************************************************** + Item_name_const methods +*****************************************************************************/ +double Item_name_const::val_real() +{ + DBUG_ASSERT(fixed); + double ret= value_item->val_real(); + null_value= value_item->null_value; + return ret; +} + + +longlong Item_name_const::val_int() +{ + DBUG_ASSERT(fixed); + longlong ret= value_item->val_int(); + null_value= value_item->null_value; + return ret; +} + + +String *Item_name_const::val_str(String *sp) +{ + DBUG_ASSERT(fixed); + String *ret= value_item->val_str(sp); + null_value= value_item->null_value; + return ret; +} + + +my_decimal *Item_name_const::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed); + my_decimal *val= value_item->val_decimal(decimal_value); + Item::null_value= value_item->null_value; + return val; +} + + +bool Item_name_const::is_null() +{ + bool ret= value_item->is_null(); + Item::null_value= value_item->null_value; + return ret; +} + +Item::Type Item_name_const::type() const +{ + return value_item->type(); +} + + +bool Item_name_const::fix_fields(THD *thd, Item **) +{ + char buf[128]; + String *item_name; + String s(buf, sizeof(buf), &my_charset_bin); + s.length(0); + + if (value_item->fix_fields(thd, &value_item) || + name_item->fix_fields(thd, &name_item)) + return TRUE; + if (!(value_item->const_item() && name_item->const_item())) + return TRUE; + + if (!(item_name= name_item->val_str(&s))) + return TRUE; /* Can't have a NULL name */ + + set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info); + max_length= value_item->max_length; + decimals= value_item->decimals; + fixed= 1; + return FALSE; +} + + +void Item_name_const::cleanup() +{ + fixed= 0; +} + + +void Item_name_const::print(String *str) +{ + str->append("NAME_CONST("); + name_item->print(str); + str->append(','); + value_item->print(str); + str->append(')'); +} + /* Move SUM items out from item tree and replace with reference diff --git a/sql/item.h b/sql/item.h index ebcd5a9da33..ab4116e4612 100644 --- a/sql/item.h +++ b/sql/item.h @@ -700,20 +700,40 @@ public: }; -// A local SP variable (incl. parameters), used in runtime +/* + A reference to local SP variable (incl. reference to SP parameter), used in + runtime. + + NOTE + This item has a "value" item, defined as + this_item() = thd->spcont->get_item(m_offset) + and it delegates everything to that item (if !this_item() then this item + poses as Item_null) except for name, which is the name of SP local + variable. +*/ + class Item_splocal : public Item { -private: - uint m_offset; +public: LEX_STRING m_name; -public: + /* + Position of this reference to SP variable in the statement (the + statement itself is in sp_instr_stmt::m_query). + This is valid only for references to SP variables in statements, + excluding DECLARE CURSOR statement. It is used to replace references to SP + variables with NAME_CONST calls when putting statements into the binary + log. + Value of 0 means that this object doesn't corresponding to reference to + SP variable in query text. + */ + int pos_in_query; - Item_splocal(LEX_STRING name, uint offset) - : m_offset(offset), m_name(name) + Item_splocal(LEX_STRING name, uint offset, int pos_in_q=0) + : m_offset(offset), m_name(name), pos_in_query(pos_in_q) { - Item::maybe_null= TRUE; + maybe_null= TRUE; } /* For error printing */ @@ -750,7 +770,7 @@ public: bool is_null(); void print(String *str); - inline void make_field(Send_field *field) + void make_field(Send_field *field) { Item *it= this_item(); @@ -761,28 +781,84 @@ public: it->make_field(field); } - inline Item_result result_type() const + Item_result result_type() const { return this_const_item()->result_type(); } - inline bool const_item() const + bool const_item() const { return TRUE; } - inline int save_in_field(Field *field, bool no_conversions) + int save_in_field(Field *field, bool no_conversions) { return this_item()->save_in_field(field, no_conversions); } - inline bool send(Protocol *protocol, String *str) + bool send(Protocol *protocol, String *str) { return this_item()->send(protocol, str); } }; +/* + NAME_CONST(given_name, const_value). + This 'function' has all properties of the supplied const_value (which is + assumed to be a literal constant), and the name given_name. + + This is used to replace references to SP variables when we write PROCEDURE + statements into the binary log. + + TODO + Together with Item_splocal and Item::this_item() we can actually extract + common a base of this class and Item_splocal. Maybe it is possible to + extract a common base with class Item_ref, too. +*/ + +class Item_name_const : public Item +{ + Item *value_item; + Item *name_item; +public: + Item_name_const(Item *name, Item *val): value_item(val), name_item(name) + { + Item::maybe_null= TRUE; + } + + bool fix_fields(THD *, Item **); + void cleanup(); + + enum Type type() const; + double val_real(); + longlong val_int(); + String *val_str(String *sp); + my_decimal *val_decimal(my_decimal *); + bool is_null(); + void print(String *str); + + Item_result result_type() const + { + return value_item->result_type(); + } + + bool const_item() const + { + return TRUE; + } + + int save_in_field(Field *field, bool no_conversions) + { + return value_item->save_in_field(field, no_conversions); + } + + inline bool send(Protocol *protocol, String *str) + { + return value_item->send(protocol, str); + } +}; + bool agg_item_collations(DTCollation &c, const char *name, Item **items, uint nitems, uint flags= 0); bool agg_item_collations_for_comparison(DTCollation &c, const char *name, diff --git a/sql/item_create.cc b/sql/item_create.cc index 77476e41d0b..82a82873ad9 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -261,6 +261,11 @@ Item *create_func_mod(Item* a, Item *b) return new Item_func_mod(a,b); } +Item *create_func_name_const(Item *a, Item *b) +{ + return new Item_name_const(a,b); +} + Item *create_func_monthname(Item* a) { return new Item_func_monthname(a); diff --git a/sql/item_create.h b/sql/item_create.h index d757318bfc1..35db9be3c89 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -65,6 +65,7 @@ Item *create_func_ltrim(Item* a); Item *create_func_md5(Item* a); Item *create_func_mod(Item* a, Item *b); Item *create_func_monthname(Item* a); +Item *create_func_name_const(Item *a, Item *b); Item *create_func_nullif(Item* a, Item *b); Item *create_func_oct(Item *); Item *create_func_ord(Item* a); diff --git a/sql/item_func.cc b/sql/item_func.cc index d3b53db2d54..13a82fa1361 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4717,11 +4717,15 @@ Item_func_sp::execute(Item **itp) m_sp->m_db.str, m_sp->m_name.str, 0, 0)) goto error_check_ctx; #endif - + /* + Disable the binlogging if this is not a SELECT statement. If this is a + SELECT, leave binlogging on, so execute_function() code writes the + function call into binlog. + */ thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION); res= m_sp->execute_function(thd, args, arg_count, itp); thd->restore_sub_statement_state(&statement_state); - + if (res && mysql_bin_log.is_open() && (m_sp->m_chistics->daccess == SP_CONTAINS_SQL || m_sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA)) diff --git a/sql/lex.h b/sql/lex.h index 7b6d86e327e..d693f501c16 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -696,6 +696,7 @@ static SYMBOL sql_functions[] = { { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB)}, { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT)}, { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB)}, + { "NAME_CONST", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_name_const)}, { "NOW", SYM(NOW_SYM)}, { "NULLIF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, { "NUMGEOMETRIES", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numgeometries)}, diff --git a/sql/log.cc b/sql/log.cc index 5ad8ec818ef..0f9e8df7dfa 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1553,6 +1553,20 @@ bool MYSQL_LOG::flush_and_sync() return err; } +void MYSQL_LOG::start_union_events(THD *thd) +{ + DBUG_ASSERT(!thd->binlog_evt_union.do_union); + thd->binlog_evt_union.do_union= TRUE; + thd->binlog_evt_union.unioned_events= FALSE; + thd->binlog_evt_union.unioned_events_trans= FALSE; +} + +void MYSQL_LOG::stop_union_events(THD *thd) +{ + DBUG_ASSERT(thd->binlog_evt_union.do_union); + thd->binlog_evt_union.do_union= FALSE; +} + /* Write an event to the binary log */ @@ -1563,6 +1577,13 @@ bool MYSQL_LOG::write(Log_event *event_info) bool error= 1; DBUG_ENTER("MYSQL_LOG::write(Log_event *)"); + if (thd->binlog_evt_union.do_union) + { + thd->binlog_evt_union.unioned_events= TRUE; + thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt; + DBUG_RETURN(0); + } + pthread_mutex_lock(&LOCK_log); /* diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 085bb0166cc..7d2a53a5e3e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -34,6 +34,7 @@ #include #include /* Needed by field.h */ #include "sql_bitmap.h" +#include "sql_array.h" #ifdef __EMX__ #undef write /* remove pthread.h macro definition for EMX */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index dfc91f5a3f4..0c962ac6979 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -588,8 +588,155 @@ sp_head::make_field(uint max_length, const char *name, TABLE *dummy) DBUG_RETURN(field); } -int -sp_head::execute(THD *thd) + +int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) +{ + return (int)((*a)->pos_in_query - (*b)->pos_in_query); +} + + +/* + StoredRoutinesBinlogging + Top-down overview: + + 1. Statements + + Statements that have is_update_query(stmt) == TRUE are written into the + binary log verbatim. + Examples: + UPDATE tbl SET tbl.x = spfunc_w_side_effects() + UPDATE tbl SET tbl.x=1 WHERE spfunc_w_side_effect_that_returns_false(tbl.y) + + Statements that have is_update_query(stmt) == FALSE (e.g. SELECTs) are not + written into binary log. Instead we catch function calls the statement + makes and write it into binary log separately (see #3). + + We actually can easily write SELECT statements into the binary log in the + right order (we don't have issues with const tables being unlocked early + because SELECTs that use FUNCTIONs unlock all tables at once) We don't do + it because replication slave thread currently can't execute SELECT + statements. Fixing this is on the TODO. + + 2. PROCEDURE calls + + CALL statements are not written into binary log. Instead + * Any FUNCTION invocation (in SET, IF, WHILE, OPEN CURSOR and other SP + instructions) is written into binlog separately. + + * Each statement executed in SP is binlogged separately, according to rules + in #1, with the exception that we modify query string: we replace uses + of SP local variables with NAME_CONST('spvar_name', ) calls. + This substitution is done in subst_spvars(). + + 3. FUNCTION calls + + In sp_head::execute_function(), we check + * If this function invocation is done from a statement that is written + into the binary log. + * If there were any attempts to write events to the binary log during + function execution. + If the answers are No and Yes, we write the function call into the binary + log as "DO spfunc(, , ...)" + +*/ + + +/* + Replace thd->query{_length} with a string that one can write to the binlog. + + SYNOPSIS + subst_spvars() + thd Current thread. + instr Instruction (we look for Item_splocal instances in + instr->free_list) + query_str Original query string + + DESCRIPTION + + The binlog-suitable string is produced by replacing references to SP local + variables with NAME_CONST('sp_var_name', value) calls. + + RETURN + 0 Ok, thd->query{_length} either has been appropraiately replaced or + there is no need for replacements. + 1 Out of memory error. +*/ + +static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) +{ + DBUG_ENTER("subst_spvars"); + if (thd->prelocked_mode == NON_PRELOCKED && mysql_bin_log.is_open()) + { + Dynamic_array sp_vars_uses; + + /* Find all instances of item_splocal used in this statement */ + for (Item *item= instr->free_list; item; item= item->next) + { + if (item->is_splocal() && ((Item_splocal*)item)->pos_in_query) + sp_vars_uses.append((Item_splocal*)item); + } + if (!sp_vars_uses.elements()) + DBUG_RETURN(0); + + /* Sort SP var refs by their occurences in the query */ + sp_vars_uses.sort(cmp_splocal_locations); + + /* + Construct a statement string where SP local var refs are replaced + with "NAME_CONST(name, value)" + */ + char buffer[512]; + String qbuf(buffer, sizeof(buffer), &my_charset_bin); + qbuf.length(0); + + char *cur= query_str->str; + int prev_pos= 0; + int res= 0; + for (Item_splocal **splocal= sp_vars_uses.front(); + splocal < sp_vars_uses.back(); splocal++) + { + /* append the text between sp ref occurences */ + res |= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); + prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; + + /* append the spvar substitute */ + res |= qbuf.append(" NAME_CONST('"); + res |= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length); + res |= qbuf.append("',"); + Item *val= (*splocal)->this_item(); + DBUG_PRINT("info", ("print %p", val)); + val->print(&qbuf); + res |= qbuf.append(')'); + if (res) + break; + } + res |= qbuf.append(cur + prev_pos, query_str->length - prev_pos); + if (res) + DBUG_RETURN(1); + + char *pbuf= thd->alloc(qbuf.length()+1); + + if (!pbuf) + DBUG_RETURN(1); + + memcpy(pbuf, qbuf.ptr(), qbuf.length()+1); + thd->query= pbuf; + thd->query_length= qbuf.length(); + } + DBUG_RETURN(0); +} + + +/* + Execute the routine. The main instruction jump loop is there + Assume the parameters already set. + + RETURN + -1 on error + +*/ + +int sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); char olddb[128]; @@ -797,9 +944,31 @@ sp_head::execute(THD *thd) } +/* + Execute a function: + - evaluate parameters + - call sp_head::execute + - evaluate the return value + + SYNOPSIS + sp_head::execute_function() + thd Thread handle + argp Passed arguments (these are items from containing statement?) + argcount Number of passed arguments. We need to check if this is + correct. + resp OUT Put result item here (q: is it a constant Item always?) + + RETURN + 0 on OK + other on error +*/ + int sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) { + Item **param_values; + ulonglong binlog_save_options; + bool need_binlog_call; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); uint csize = m_pcont->max_pvars(); @@ -823,6 +992,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) goto end; } + if (!(param_values= (Item**)thd->alloc(sizeof(Item*)*argcount))) + DBUG_RETURN(-1); // QQ Should have some error checking here? (types, etc...) if (!(nctx= new sp_rcontext(csize, hmax, cmax))) @@ -831,6 +1002,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL, FALSE); + param_values[i]= it; if (!it) goto end; // EOM error @@ -855,7 +1027,47 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) } thd->spcont= nctx; + binlog_save_options= thd->options; + need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG); + if (need_binlog_call) + mysql_bin_log.start_union_events(thd); + + thd->options&= ~OPTION_BIN_LOG; ret= execute(thd); + thd->options= binlog_save_options; + + if (need_binlog_call) + mysql_bin_log.stop_union_events(thd); + + if (thd->binlog_evt_union.unioned_events) + { + char buf[64]; + String bufstr(buf, sizeof(buf), &my_charset_bin); + bufstr.length(0); + bufstr.append("DO ", 3); + append_identifier(thd, &bufstr, m_name.str, m_name.length); + bufstr.append('('); + for (uint i=0; i < argcount; i++) + { + if (i) + bufstr.append(','); + param_values[i]->print(&bufstr); + } + bufstr.append(')'); + + if (mysql_bin_log.is_open()) + { + bool transactional_table= FALSE; + Query_log_event qinfo(thd, bufstr.ptr(), bufstr.length(), + thd->binlog_evt_union.unioned_events_trans, FALSE); + if (mysql_bin_log.write(&qinfo) && transactional_table) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "Invoked ROUTINE modified a transactional table but MYSQL" + "failed to reflect this change in the binary log."); + } + } + } if (m_type == TYPE_ENUM_FUNCTION && ret == 0) { @@ -893,6 +1105,25 @@ static Item_func_get_user_var *item_is_user_var(Item *it) } +/* + Execute a procedure. + SYNOPSIS + sp_head::execute_procedure() + thd Thread handle + args List of values passed as arguments. + + DESCRIPTION + + The function does the following steps: + - Set all parameters + - call sp_head::execute + - copy back values of INOUT and OUT parameters + + RETURN + 0 Ok + -1 Error +*/ + int sp_head::execute_procedure(THD *thd, List *args) { int ret= 0; @@ -928,7 +1159,7 @@ int sp_head::execute_procedure(THD *thd, List *args) thd->spcont= save_spcont; DBUG_RETURN(-1); } - + if (csize > 0 || hmax > 0 || cmax > 0) { Item_null *nit= NULL; // Re-use this, and only create if needed @@ -1105,7 +1336,7 @@ int sp_head::execute_procedure(THD *thd, List *args) nctx->pop_all_cursors(); // To avoid memory leaks after an error delete nctx; // Does nothing thd->spcont= save_spcont; - + DBUG_RETURN(ret); } @@ -1447,8 +1678,12 @@ sp_head::show_create_function(THD *thd) DBUG_RETURN(res); } -void -sp_head::optimize() + +/* + TODO: what does this do?? +*/ + +void sp_head::optimize() { List bp; sp_instr *i; @@ -1636,7 +1871,6 @@ int sp_instr::exec_core(THD *thd, uint *nextp) return 0; } - /* sp_instr_stmt class functions */ @@ -1646,9 +1880,9 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) { char *query; uint32 query_length; + int res; DBUG_ENTER("sp_instr_stmt::execute"); DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command())); - int res; query= thd->query; query_length= thd->query_length; @@ -1657,8 +1891,10 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) if (query_cache_send_result_to_client(thd, thd->query, thd->query_length) <= 0) { + thd->query_str_binlog_unsuitable= subst_spvars(thd, this, &m_query); res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this); query_cache_end_of_result(thd); + thd->query_str_binlog_unsuitable= FALSE; } else *nextp= m_ip+1; diff --git a/sql/sp_head.h b/sql/sp_head.h index 8ae7834eb2a..963d9da07cf 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -326,10 +326,22 @@ public: virtual ~sp_instr() { free_items(); } - // Execute this instrution. '*nextp' will be set to the index of the next - // instruction to execute. (For most instruction this will be the - // instruction following this one.) - // Returns 0 on success, non-zero if some error occured. + + /* + Execute this instruction + + SYNOPSIS + execute() + thd Thread handle + nextp OUT index of the next instruction to execute. (For most + instructions this will be the instruction following this + one). + + RETURN + 0 on success, + other if some error occured + */ + virtual int execute(THD *thd, uint *nextp) = 0; /* @@ -339,7 +351,7 @@ public: Should be implemented for instructions using expressions or whole statements (thus having to have own LEX). Used in concert with - sp_lex_keeper class and its descendants. + sp_lex_keeper class and its descendants (there are none currently). */ virtual int exec_core(THD *thd, uint *nextp); @@ -808,6 +820,7 @@ private: }; // class sp_instr_hreturn : public sp_instr +/* This is DECLARE CURSOR */ class sp_instr_cpush : public sp_instr { sp_instr_cpush(const sp_instr_cpush &); /* Prevent use of these */ diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 0d218bc0538..196f9ccb24b 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -72,6 +72,11 @@ typedef struct sp_cond sp_cond_type_t *val; } sp_cond_t; + +/* + This seems to be an "SP parsing context" or something. +*/ + class sp_pcontext : public Sql_alloc { sp_pcontext(const sp_pcontext &); /* Prevent use of these */ diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index dedbc7bdef1..36380952e5d 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -41,6 +41,16 @@ typedef struct uint foffset; // Frame offset for the handlers declare level } sp_handler_t; + +/* + This is a run context? of one SP ? + THis is + - a stack of cursors? + - a stack of handlers? + - a stack of Items ? + - a stack of instruction locations in SP? +*/ + class sp_rcontext : public Sql_alloc { sp_rcontext(const sp_rcontext &); /* Prevent use of these */ diff --git a/sql/sql_array.h b/sql/sql_array.h new file mode 100644 index 00000000000..c68caf74b25 --- /dev/null +++ b/sql/sql_array.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include + +/* + A typesafe wrapper around DYNAMIC_ARRAY +*/ + +template class Dynamic_array +{ + DYNAMIC_ARRAY array; +public: + Dynamic_array(uint prealloc=16, uint increment=16) + { + my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment); + } + + Elem& at(int idx) + { + return *(((Elem*)array.buffer) + idx); + } + + Elem *front() + { + return (Elem*)array.buffer; + } + + Elem *back() + { + return ((Elem*)array.buffer) + array.elements; + } + + bool append(Elem &el) + { + return (insert_dynamic(&array, (gptr)&el)); + } + + int elements() + { + return array.elements; + } + + ~Dynamic_array() + { + delete_dynamic(&array); + } + + typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2); + + void sort(CMP_FUNC cmp_func) + { + qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); + } +}; + diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d4f05456cad..dcc3715a2b6 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -178,7 +178,7 @@ THD::THD() rand_used(0), time_zone_used(0), last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), - spcont(NULL) + spcont(NULL), query_str_binlog_unsuitable(FALSE) { current_arena= this; host= user= priv_user= db= ip= 0; @@ -210,6 +210,7 @@ THD::THD() db_charset= global_system_variables.collation_database; bzero(ha_data, sizeof(ha_data)); mysys_var=0; + binlog_evt_union.do_union= FALSE; #ifndef DBUG_OFF dbug_sentry=THD_SENTRY_MAGIC; #endif @@ -1888,7 +1889,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->cuted_fields= cuted_fields; backup->client_capabilities= client_capabilities; - options&= ~OPTION_BIN_LOG; + if (!lex->requires_prelocking() || is_update_query(lex->sql_command)) + options&= ~OPTION_BIN_LOG; /* Disable result sets */ client_capabilities &= ~CLIENT_MULTI_RESULTS; in_sub_stmt|= new_state; diff --git a/sql/sql_class.h b/sql/sql_class.h index a8d45a3a6b4..625fdae68f5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -311,6 +311,9 @@ public: bool write(Log_event* event_info); // binary log write bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event); + void start_union_events(THD *thd); + void stop_union_events(THD *thd); + /* v stands for vector invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0) @@ -1346,7 +1349,34 @@ public: my_bool my_bool_value; long long_value; } sys_var_tmp; - + + /* + If true, thd->query is not a suitable query to write to binary log. This + is not handled everywhere currently - we check it only in statements + that can have SP variable references. + */ + bool query_str_binlog_unsuitable; + + struct { + /* + If true, mysql_bin_log::write(Log_event) call will not write events to + binlog, and maintain 2 below variables instead (use + mysql_bin_log.start_union_events to turn this on) + */ + bool do_union; + /* + If TRUE, at least one mysql_bin_log::write(Log_event) call has been + made after last mysql_bin_log.start_union_events() call. + */ + bool unioned_events; + /* + If TRUE, at least one mysql_bin_log::write(Log_event e), where + e.cache_stmt == TRUE call has been made after last + mysql_bin_log.start_union_events() call. + */ + bool unioned_events_trans; + } binlog_evt_union; + THD(); ~THD(); @@ -1968,7 +1998,12 @@ class multi_delete :public select_result_interceptor ha_rows deleted, found; uint num_of_tables; int error; - bool do_delete, transactional_tables, normal_tables, delete_while_scanning; + bool do_delete; + /* True if at least one table we delete from is transactional */ + bool transactional_tables; + /* True if at least one table we delete from is not transactional */ + bool normal_tables; + bool delete_while_scanning; public: multi_delete(TABLE_LIST *dt, uint num_of_tables); @@ -1995,7 +2030,10 @@ class multi_update :public select_result_interceptor uint table_count; Copy_field *copy_field; enum enum_duplicates handle_duplicates; - bool do_update, trans_safe, transactional_tables, ignore; + bool do_update, trans_safe; + /* True if the update operation has made a change in a transactional table */ + bool transactional_tables; + bool ignore; public: multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list, diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 35183fc959b..7c012e3b442 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -254,7 +254,8 @@ cleanup: thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_table, FALSE); - if (mysql_bin_log.write(&qinfo) && transactional_table) + if ((thd->query_str_binlog_unsuitable || mysql_bin_log.write(&qinfo)) + && transactional_table) error=1; } if (!transactional_table) @@ -719,7 +720,8 @@ bool multi_delete::send_eof() thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_tables, FALSE); - if (mysql_bin_log.write(&qinfo) && !normal_tables) + if ((thd->query_str_binlog_unsuitable || mysql_bin_log.write(&qinfo)) + && !normal_tables) local_error=1; // Log write failed: roll back the SQL statement } if (!transactional_tables) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 93c9991418d..d484f3e48a6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -592,7 +592,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_table, FALSE); - if (mysql_bin_log.write(&qinfo) && transactional_table) + if ((thd->query_str_binlog_unsuitable || + mysql_bin_log.write(&qinfo)) && transactional_table) error=1; } if (!transactional_table) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 031d133a40c..86823919378 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -517,6 +517,10 @@ int yylex(void *arg, void *yythd) uchar *ident_map= cs->ident_map; lex->yylval=yylval; // The global state + + lex->tok_end_prev= lex->tok_end; + lex->tok_start_prev= lex->tok_start; + lex->tok_start=lex->tok_end=lex->ptr; state=lex->next_state; lex->next_state=MY_LEX_OPERATOR_OR_IDENT; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 59969ea09fa..d777abca29a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -703,6 +703,10 @@ typedef struct st_lex SELECT_LEX *all_selects_list; uchar *buf; /* The beginning of string, used by SPs */ uchar *ptr,*tok_start,*tok_end,*end_of_query; + + /* The values of tok_start/tok_end as they were one call of yylex before */ + uchar *tok_start_prev, *tok_end_prev; + char *length,*dec,*change,*name; char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c86b7eba024..26e5601a35e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2253,6 +2253,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) return FALSE; } + /**************************************************************************** ** mysql_execute_command ** Execute command saved in thd and current_lex->sql_command @@ -4217,28 +4218,16 @@ end_with_restore_list: thd->variables.select_limit= HA_POS_ERROR; thd->row_count_func= 0; - tmp_disable_binlog(thd); /* don't binlog the substatements */ - res= sp->execute_procedure(thd, &lex->value_list); - reenable_binlog(thd); - - /* - We write CALL to binlog; on the opposite we didn't write the - substatements. That choice is necessary because the substatements - may use local vars. - Binlogging should happen when all tables are locked. They are locked - just above, and unlocked by close_thread_tables(). All tables which - are to be updated are locked like with a table-level write lock, and - this also applies to InnoDB (I tested - note that it reduces - InnoDB's concurrency as we don't use row-level locks). So binlogging - below is safe. - Note the limitation: if the SP returned an error, but still did some - updates, we do NOT binlog it. This is because otherwise "permission - denied", "table does not exist" etc would stop the slave quite - often. There is no easy way to know if the SP updated something - (even no_trans_update is not suitable, as it may be a transactional - autocommit update which happened, and no_trans_update covers only - INSERT/UPDATE/LOAD). + + /* + We never write CALL statements int binlog: + - If the mode is non-prelocked, each statement will be logged + separately. + - If the mode is prelocked, the invoking statement will care + about writing into binlog. + So just execute the statement. */ + res= sp->execute_procedure(thd, &lex->value_list); if (mysql_bin_log.is_open() && (sp->m_chistics->daccess == SP_CONTAINS_SQL || sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA)) @@ -4248,11 +4237,7 @@ end_with_restore_list: ER_FAILED_ROUTINE_BREAK_BINLOG, ER(ER_FAILED_ROUTINE_BREAK_BINLOG)); else - { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } } /* @@ -5405,8 +5390,10 @@ void mysql_parse(THD *thd, char *inBuf, uint length) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex= thd->lex; + sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); + if (!yyparse((void *)thd) && ! thd->is_fatal_error) { #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b596420692a..e9330d86b8f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -475,7 +475,8 @@ int mysql_update(THD *thd, thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_table, FALSE); - if (mysql_bin_log.write(&qinfo) && transactional_table) + if ((thd->query_str_binlog_unsuitable || mysql_bin_log.write(&qinfo)) + && transactional_table) error=1; // Rollback update } if (!transactional_table) @@ -1441,7 +1442,8 @@ bool multi_update::send_eof() thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_tables, FALSE); - if (mysql_bin_log.write(&qinfo) && trans_safe) + if ((thd->query_str_binlog_unsuitable || mysql_bin_log.write(&qinfo)) + && trans_safe) local_error= 1; // Rollback update } if (!transactional_tables) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b446a06ded1..3727e2db5a3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7133,10 +7133,13 @@ simple_ident: sp_pvar_t *spv; LEX *lex = Lex; sp_pcontext *spc = lex->spcont; - if (spc && (spv = spc->find_pvar(&$1))) - { /* We're compiling a stored procedure and found a variable */ - $$ = (Item*) new Item_splocal($1, spv->offset); + { + /* We're compiling a stored procedure and found a variable */ + Item_splocal *splocal; + splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev - + lex->sphead->m_tmp_query); + $$ = (Item*) splocal; lex->variables_used= 1; lex->safe_to_cache_query=0; } From 0f94385b651a26ed7d3a8085941ab417acc692d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 16:57:13 +0300 Subject: [PATCH 79/80] ha_innodb.cc: Fix typo sql/ha_innodb.cc: Fix typo --- sql/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a27f1942158..3527f66f023 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5426,7 +5426,7 @@ ha_innobase::info( is an accurate estimate if it is zero. Of course, it is not, since we do not have any locks on the rows yet at this phase. Since SHOW TABLE STATUS seems to call this function with the - HA_STATUS_TIME flag set, while the left join optizer does not + HA_STATUS_TIME flag set, while the left join optimizer does not set that flag, we add one to a zero value if the flag is not set. That way SHOW TABLE STATUS will show the best estimate, while the optimizer never sees the table empty. */ From b8cf4e659a55a7e59e48952427cc46a0c06e0227 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Aug 2005 18:13:56 +0400 Subject: [PATCH 80/80] BUG#12335: merging: temporarily removed a test case that demonstrates wrong behaviour and does it in non-deterministic way. --- mysql-test/r/rpl_sp_effects.result | 58 ---------------------- mysql-test/t/rpl_sp_effects.test | 79 ------------------------------ 2 files changed, 137 deletions(-) diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result index 738fd08450a..8bcbf1a60d0 100644 --- a/mysql-test/r/rpl_sp_effects.result +++ b/mysql-test/r/rpl_sp_effects.result @@ -156,61 +156,3 @@ slave: 6 drop procedure p1; drop function f1; drop table t1,t2; -create table t1 (a int); -create table t2 (a char(200)); -create procedure p1() -begin -declare dummy int; -while ((select count(*) from t1) < 1) do -set dummy = sleep(1); -end while; -end// -create procedure p2() -begin -select f1(); -call p1(); -delete from t1 limit 1; -select f1(); -call p1(); -delete from t1 limit 1; -select f1(); -end// -create function f1() returns int -begin -insert into t2 values('f1-r1'); -return 0; -end// - call p2(); -drop function f1// -create function f1() returns int -begin -insert into t2 values('f1-r2'); -return 0; -end// -insert into t1 values (1) // -call p1()// -drop function f1// -create function f1() returns int -begin -insert into t2 values('f1-r3'); -return 0; -end// -insert into t1 values (1) // -call p1()// -f1() -0 -f1() -0 -f1() -0 -select * from t2; -a -f1-r1 -f1-r1 -f1-r1 -select * from t2; -a -f1-r1 -f1-r3 -f1-r3 -drop table t1; diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test index 825fd764f4d..f8e83eabe90 100644 --- a/mysql-test/t/rpl_sp_effects.test +++ b/mysql-test/t/rpl_sp_effects.test @@ -153,82 +153,3 @@ drop function f1; drop table t1,t2; sync_slave_with_master; - -# The following will produce incorrect results: -connection master; -create table t1 (a int); -create table t2 (a char(200)); - -delimiter //; -create procedure p1() -begin - declare dummy int; - while ((select count(*) from t1) < 1) do - set dummy = sleep(1); - end while; -end// - -create procedure p2() -begin - select f1(); - - call p1(); - delete from t1 limit 1; - - select f1(); - - call p1(); - delete from t1 limit 1; - - select f1(); -end// - -create function f1() returns int -begin - insert into t2 values('f1-r1'); - return 0; -end// -delimiter ;// - -connection master; -send call p2(); - -connection master1; -delimiter //; - -drop function f1// -create function f1() returns int -begin - insert into t2 values('f1-r2'); - return 0; -end// -insert into t1 values (1) // - -call p1()// - -drop function f1// -create function f1() returns int -begin - insert into t2 values('f1-r3'); - return 0; -end// -insert into t1 values (1) // - -call p1()// - -delimiter ;// - -connection master; -reap; - -select * from t2; - -connection slave; -select * from t2; - -# Clean up -connection master; -drop table t1; - -sync_slave_with_master; -