Commit d0c7c5fe authored by konstantin@mysql.com's avatar konstantin@mysql.com

Merge mysql.com:/opt/local/work/mysql-5.0-root

into  mysql.com:/opt/local/work/mysql-5.0-runtime-merge
parents a6904ef0 3148efad
...@@ -3699,6 +3699,37 @@ os_aio_posix_handle( ...@@ -3699,6 +3699,37 @@ os_aio_posix_handle(
} }
#endif #endif
/**************************************************************************
Do a 'last millisecond' check that the page end is sensible;
reported page checksum errors from Linux seem to wipe over the page end. */
static
void
os_file_check_page_trailers(
/*========================*/
byte* combined_buf, /* in: combined write buffer */
ulint total_len) /* in: size of combined_buf, in bytes
(a multiple of UNIV_PAGE_SIZE) */
{
ulint len;
for (len = 0; len + UNIV_PAGE_SIZE <= total_len;
len += UNIV_PAGE_SIZE) {
byte* buf = combined_buf + len;
if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: ERROR: The page to be written seems corrupt!\n"
"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n",
(ulong)total_len, (ulong)len);
buf_page_print(buf);
fprintf(stderr,
"InnoDB: ERROR: The page to be written seems corrupt!\n");
}
}
}
/************************************************************************** /**************************************************************************
Does simulated aio. This function should be called by an i/o-handler Does simulated aio. This function should be called by an i/o-handler
thread. */ thread. */
...@@ -3736,7 +3767,6 @@ os_aio_simulated_handle( ...@@ -3736,7 +3767,6 @@ os_aio_simulated_handle(
ibool ret; ibool ret;
ulint n; ulint n;
ulint i; ulint i;
ulint len2;
segment = os_aio_get_array_and_local_segment(&array, global_segment); segment = os_aio_get_array_and_local_segment(&array, global_segment);
...@@ -3943,33 +3973,16 @@ os_aio_simulated_handle( ...@@ -3943,33 +3973,16 @@ os_aio_simulated_handle(
(ulong) total_len); (ulong) total_len);
ut_error; ut_error;
} }
/* Do a 'last millisecond' check that the page end os_file_check_page_trailers(combined_buf, total_len);
is sensible; reported page checksum errors from
Linux seem to wipe over the page end */
for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len;
len2 += UNIV_PAGE_SIZE) {
if (mach_read_from_4(combined_buf + len2
+ FIL_PAGE_LSN + 4)
!= mach_read_from_4(combined_buf + len2
+ UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: ERROR: The page to be written seems corrupt!\n");
fprintf(stderr,
"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n",
(ulong)total_len, (ulong)len2);
buf_page_print(combined_buf + len2);
fprintf(stderr,
"InnoDB: ERROR: The page to be written seems corrupt!\n");
}
}
} }
ret = os_file_write(slot->name, slot->file, combined_buf, ret = os_file_write(slot->name, slot->file, combined_buf,
slot->offset, slot->offset_high, total_len); slot->offset, slot->offset_high, total_len);
if (array == os_aio_write_array) {
os_file_check_page_trailers(combined_buf, total_len);
}
} else { } else {
ret = os_file_read(slot->file, combined_buf, ret = os_file_read(slot->file, combined_buf,
slot->offset, slot->offset_high, total_len); slot->offset, slot->offset_high, total_len);
......
...@@ -189,4 +189,9 @@ HEX(f) ...@@ -189,4 +189,9 @@ HEX(f)
select HEX(f) from t4; select HEX(f) from t4;
HEX(f) HEX(f)
835C 835C
drop table t1, t2, t03, t04, t3, t4; flush logs;
select * from t5 /* must be (1),(1) */;
a
1
1
drop table t1, t2, t03, t04, t3, t4, t5;
...@@ -29,9 +29,40 @@ n ...@@ -29,9 +29,40 @@ n
2 2
3 3
4 4
show slave status; SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Slave_IO_State #
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-bin.000001 319 No # Master_Host 127.0.0.1
Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 776
Relay_Log_File slave-relay-bin.000004
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running #
Slave_SQL_Running No
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 319
Relay_Log_Space #
Until_Condition Master
Until_Log_File master-bin.000001
Until_Log_Pos 319
Master_SSL_Allowed No
Master_SSL_CA_File
Master_SSL_CA_Path
Master_SSL_Cert
Master_SSL_Cipher
Master_SSL_Key
Seconds_Behind_Master #
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
select * from t1; select * from t1;
n n
...@@ -39,23 +70,116 @@ n ...@@ -39,23 +70,116 @@ n
2 2
3 3
4 4
show slave status; SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Slave_IO_State #
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-no-such-bin.000001 291 No # Master_Host 127.0.0.1
Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 776
Relay_Log_File slave-relay-bin.000004
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running #
Slave_SQL_Running No
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 319
Relay_Log_Space #
Until_Condition Master
Until_Log_File master-no-such-bin.000001
Until_Log_Pos 291
Master_SSL_Allowed No
Master_SSL_CA_File
Master_SSL_CA_Path
Master_SSL_Cert
Master_SSL_Cipher
Master_SSL_Key
Seconds_Behind_Master #
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
select * from t2; select * from t2;
n n
1 1
2 2
show slave status; SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Slave_IO_State #
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 608 # Relay slave-relay-bin.000004 746 No # Master_Host 127.0.0.1
Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 776
Relay_Log_File slave-relay-bin.000004
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running #
Slave_SQL_Running No
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 608
Relay_Log_Space #
Until_Condition Relay
Until_Log_File slave-relay-bin.000004
Until_Log_Pos 746
Master_SSL_Allowed No
Master_SSL_CA_File
Master_SSL_CA_Path
Master_SSL_Cert
Master_SSL_Cipher
Master_SSL_Key
Seconds_Behind_Master #
start slave; start slave;
stop slave; stop slave;
start slave until master_log_file='master-bin.000001', master_log_pos=776; start slave until master_log_file='master-bin.000001', master_log_pos=776;
show slave status; SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Slave_IO_State #
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 776 # Master master-bin.000001 776 No # Master_Host 127.0.0.1
Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 776
Relay_Log_File slave-relay-bin.000004
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running Yes
Slave_SQL_Running No
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 776
Relay_Log_Space #
Until_Condition Master
Until_Log_File master-bin.000001
Until_Log_Pos 776
Master_SSL_Allowed No
Master_SSL_CA_File
Master_SSL_CA_Path
Master_SSL_Cert
Master_SSL_Cipher
Master_SSL_Key
Seconds_Behind_Master #
start slave until master_log_file='master-bin', master_log_pos=561; start slave until master_log_file='master-bin', master_log_pos=561;
ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
......
...@@ -122,9 +122,17 @@ select HEX(f) from t3; ...@@ -122,9 +122,17 @@ select HEX(f) from t3;
select HEX(f) from t04; select HEX(f) from t04;
select HEX(f) from t4; select HEX(f) from t4;
#
#14157: utf8 encoding in binlog without set character_set_client
#
flush logs;
--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `` (a int); insert into `` values (1); insert into t5 select * from ``'
# resulted log is client charset insensitive (latin1 not koi8r) as it must be
--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1
select * from t5 /* must be (1),(1) */;
# clean up # clean up
drop table t1, t2, t03, t04, t3, t4; drop table t1, t2, t03, t04, t3, t4, t5;
# End of 4.1 tests # End of 5.0 tests
...@@ -163,24 +163,19 @@ drop table t5; ...@@ -163,24 +163,19 @@ drop table t5;
# value was set up at the moment of temp table creation # value was set up at the moment of temp table creation
# #
connection con1; connection con1;
set @session.pseudo_thread_id=100; set @@session.pseudo_thread_id=100;
create temporary table t101 (id int); create temporary table t101 (id int);
create temporary table t102 (id int); create temporary table t102 (id int);
set @session.pseudo_thread_id=200; set @@session.pseudo_thread_id=200;
create temporary table t201 (id int); create temporary table t201 (id int);
create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int); create temporary table `t``201` (id int);
# emulate internal temp table not to come to binlog
# create temporary table `#sql_not_user_table202` (id int);
# Don't kill our own connection to the server as set @@session.pseudo_thread_id=300;
# the result code differs depending on platform. create temporary table t301 (id int);
# create temporary table t302 (id int);
# Select the id to kill into a variable of mysqltest create temporary table `#sql_not_user_table303` (id int);
let $con1_id= `select connection_id()`; disconnect con1;
# Switch connection to avoid killing our own connection
connection master;
--disable_query_log
eval kill $con1_id;
--enable_query_log
#now do something to show that slave is ok after DROP temp tables #now do something to show that slave is ok after DROP temp tables
connection master; connection master;
...@@ -194,4 +189,16 @@ select * from t1 /* must be 1 */; ...@@ -194,4 +189,16 @@ select * from t1 /* must be 1 */;
connection master; connection master;
drop table t1; drop table t1;
#
#14157: utf8 encoding in binlog without set character_set_client
#
--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t1 select * from `ÑÝÉË`'
sync_slave_with_master;
#connection slave;
select * from t1;
connection master;
drop table t1;
# End of 5.0 tests # End of 5.0 tests
...@@ -31,7 +31,7 @@ wait_for_slave_to_stop; ...@@ -31,7 +31,7 @@ wait_for_slave_to_stop;
select * from t1; select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT --replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 # --replace_column 1 # 9 # 11 # 23 # 33 #
show slave status; --query_vertical SHOW SLAVE STATUS
# this should fail right after start # this should fail right after start
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
...@@ -41,7 +41,7 @@ sleep 2; ...@@ -41,7 +41,7 @@ sleep 2;
wait_for_slave_to_stop; wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_MYPORT --replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 # --replace_column 1 # 9 # 11 # 23 # 33 #
show slave status; --query_vertical SHOW SLAVE STATUS
# try replicate all until second insert to t2; # try replicate all until second insert to t2;
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
...@@ -50,7 +50,7 @@ wait_for_slave_to_stop; ...@@ -50,7 +50,7 @@ wait_for_slave_to_stop;
select * from t2; select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT --replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 # --replace_column 1 # 9 # 11 # 23 # 33 #
show slave status; --query_vertical SHOW SLAVE STATUS
# clean up # clean up
start slave; start slave;
...@@ -67,7 +67,7 @@ wait_for_slave_to_stop; ...@@ -67,7 +67,7 @@ wait_for_slave_to_stop;
# here the sql slave thread should be stopped # here the sql slave thread should be stopped
--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
--replace_column 1 # 9 # 23 # 33 # --replace_column 1 # 9 # 23 # 33 #
show slave status; --query_vertical SHOW SLAVE STATUS
#testing various error conditions #testing various error conditions
--error 1277 --error 1277
......
...@@ -4048,6 +4048,9 @@ ha_innobase::index_prev( ...@@ -4048,6 +4048,9 @@ ha_innobase::index_prev(
mysql_byte* buf) /* in/out: buffer for previous row in MySQL mysql_byte* buf) /* in/out: buffer for previous row in MySQL
format */ format */
{ {
statistic_increment(current_thd->status_var.ha_read_prev_count,
&LOCK_status);
return(general_fetch(buf, ROW_SEL_PREV, 0)); return(general_fetch(buf, ROW_SEL_PREV, 0));
} }
......
...@@ -958,7 +958,7 @@ void Item_splocal::print(String *str) ...@@ -958,7 +958,7 @@ void Item_splocal::print(String *str)
} }
bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item *it) bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
{ {
return ctx->set_variable(thd, get_var_idx(), it); return ctx->set_variable(thd, get_var_idx(), it);
} }
...@@ -5375,9 +5375,9 @@ void Item_trigger_field::set_required_privilege(bool rw) ...@@ -5375,9 +5375,9 @@ void Item_trigger_field::set_required_privilege(bool rw)
} }
bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item *it) bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it)
{ {
Item *item= sp_prepare_func_item(thd, &it); Item *item= sp_prepare_func_item(thd, it);
return (!item || (!fixed && fix_fields(thd, 0)) || return (!item || (!fixed && fix_fields(thd, 0)) ||
(item->save_in_field(field, 0) < 0)); (item->save_in_field(field, 0) < 0));
......
...@@ -404,7 +404,7 @@ class Settable_routine_parameter ...@@ -404,7 +404,7 @@ class Settable_routine_parameter
FALSE if parameter value has been set, FALSE if parameter value has been set,
TRUE if error has occured. TRUE if error has occured.
*/ */
virtual bool set_value(THD *thd, sp_rcontext *ctx, Item *it)= 0; virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0;
}; };
...@@ -928,7 +928,7 @@ class Item_splocal :public Item_sp_variable, ...@@ -928,7 +928,7 @@ class Item_splocal :public Item_sp_variable,
inline Item_result result_type() const; inline Item_result result_type() const;
private: private:
bool set_value(THD *thd, sp_rcontext *ctx, Item *it); bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
public: public:
Settable_routine_parameter *get_settable_routine_parameter() Settable_routine_parameter *get_settable_routine_parameter()
...@@ -2188,7 +2188,7 @@ class Item_trigger_field : public Item_field, ...@@ -2188,7 +2188,7 @@ class Item_trigger_field : public Item_field,
private: private:
void set_required_privilege(bool rw); void set_required_privilege(bool rw);
bool set_value(THD *thd, sp_rcontext *ctx, Item *it); bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
public: public:
Settable_routine_parameter *get_settable_routine_parameter() Settable_routine_parameter *get_settable_routine_parameter()
...@@ -2196,7 +2196,7 @@ class Item_trigger_field : public Item_field, ...@@ -2196,7 +2196,7 @@ class Item_trigger_field : public Item_field,
return (read_only ? 0 : this); return (read_only ? 0 : this);
} }
bool set_value(THD *thd, Item *it) bool set_value(THD *thd, Item **it)
{ {
return set_value(thd, NULL, it); return set_value(thd, NULL, it);
} }
......
...@@ -4121,14 +4121,14 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const ...@@ -4121,14 +4121,14 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
bool Item_func_get_user_var::set_value(THD *thd, bool Item_func_get_user_var::set_value(THD *thd,
sp_rcontext */*ctx*/, Item *it) sp_rcontext */*ctx*/, Item **it)
{ {
Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), it); Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
/* /*
Item_func_set_user_var is not fixed after construction, call Item_func_set_user_var is not fixed after construction, call
fix_fields(). fix_fields().
*/ */
return (!suv || suv->fix_fields(thd, &it) || suv->check() || suv->update()); return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
} }
......
...@@ -1209,7 +1209,7 @@ class Item_func_get_user_var :public Item_func, ...@@ -1209,7 +1209,7 @@ class Item_func_get_user_var :public Item_func,
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
private: private:
bool set_value(THD *thd, sp_rcontext *ctx, Item *it); bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
public: public:
Settable_routine_parameter *get_settable_routine_parameter() Settable_routine_parameter *get_settable_routine_parameter()
......
...@@ -1577,6 +1577,16 @@ inline int hexchar_to_int(char c) ...@@ -1577,6 +1577,16 @@ inline int hexchar_to_int(char c)
return -1; return -1;
} }
/*
is_user_table()
return true if the table was created explicitly
*/
inline bool is_user_table(TABLE * table)
{
const char *name= table->s->table_name;
return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
}
/* /*
Some functions that are different in the embedded library and the normal Some functions that are different in the embedded library and the normal
......
...@@ -310,11 +310,13 @@ sp_prepare_func_item(THD* thd, Item **it_addr) ...@@ -310,11 +310,13 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
*/ */
bool bool
sp_eval_expr(THD *thd, Field *result_field, Item *expr_item) sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
{ {
Item *expr_item;
DBUG_ENTER("sp_eval_expr"); DBUG_ENTER("sp_eval_expr");
if (!(expr_item= sp_prepare_func_item(thd, &expr_item))) if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
bool err_status= FALSE; bool err_status= FALSE;
...@@ -1281,7 +1283,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, ...@@ -1281,7 +1283,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
/* Arguments must be fixed in Item_func_sp::fix_fields */ /* Arguments must be fixed in Item_func_sp::fix_fields */
DBUG_ASSERT(argp[arg_no]->fixed); DBUG_ASSERT(argp[arg_no]->fixed);
if ((err_status= nctx->set_variable(thd, arg_no, argp[arg_no]))) if ((err_status= nctx->set_variable(thd, arg_no, &(argp[arg_no]))))
goto err_with_cleanup; goto err_with_cleanup;
} }
...@@ -1485,7 +1487,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -1485,7 +1487,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
Item_null *null_item= new Item_null(); Item_null *null_item= new Item_null();
if (!null_item || if (!null_item ||
nctx->set_variable(thd, i, null_item)) nctx->set_variable(thd, i, (struct Item **)&null_item))
{ {
err_status= TRUE; err_status= TRUE;
break; break;
...@@ -1493,7 +1495,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -1493,7 +1495,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
} }
else else
{ {
if (nctx->set_variable(thd, i, *it_args.ref())) if (nctx->set_variable(thd, i, it_args.ref()))
{ {
err_status= TRUE; err_status= TRUE;
break; break;
...@@ -1550,7 +1552,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -1550,7 +1552,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
DBUG_ASSERT(srp); DBUG_ASSERT(srp);
if (srp->set_value(thd, octx, nctx->get_item(i))) if (srp->set_value(thd, octx, nctx->get_item_addr(i)))
{ {
err_status= TRUE; err_status= TRUE;
break; break;
...@@ -2326,7 +2328,7 @@ sp_instr_set::execute(THD *thd, uint *nextp) ...@@ -2326,7 +2328,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
int int
sp_instr_set::exec_core(THD *thd, uint *nextp) sp_instr_set::exec_core(THD *thd, uint *nextp)
{ {
int res= thd->spcont->set_variable(thd, m_offset, m_value); int res= thd->spcont->set_variable(thd, m_offset, &m_value);
if (res && thd->spcont->found_handler_here()) if (res && thd->spcont->found_handler_here())
{ {
...@@ -2391,7 +2393,7 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp) ...@@ -2391,7 +2393,7 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
int int
sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp) sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
{ {
const int res= (trigger_field->set_value(thd, value) ? -1 : 0); const int res= (trigger_field->set_value(thd, &value) ? -1 : 0);
*nextp = m_ip+1; *nextp = m_ip+1;
return res; return res;
} }
...@@ -2596,7 +2598,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) ...@@ -2596,7 +2598,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
do it in scope of execution the current context/block. do it in scope of execution the current context/block.
*/ */
return thd->spcont->set_return_value(thd, m_value); return thd->spcont->set_return_value(thd, &m_value);
} }
void void
...@@ -3040,7 +3042,7 @@ sp_instr_set_case_expr::execute(THD *thd, uint *nextp) ...@@ -3040,7 +3042,7 @@ sp_instr_set_case_expr::execute(THD *thd, uint *nextp)
int int
sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
{ {
int res= thd->spcont->set_case_expr(thd, m_case_expr_id, m_case_expr); int res= thd->spcont->set_case_expr(thd, m_case_expr_id, &m_case_expr);
if (res && if (res &&
!thd->spcont->get_case_expr(m_case_expr_id) && !thd->spcont->get_case_expr(m_case_expr_id) &&
...@@ -3054,7 +3056,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) ...@@ -3054,7 +3056,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
Item *null_item= new Item_null(); Item *null_item= new Item_null();
if (!null_item || if (!null_item ||
thd->spcont->set_case_expr(thd, m_case_expr_id, null_item)) thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item))
{ {
/* If this also failed, we have to abort. */ /* If this also failed, we have to abort. */
......
...@@ -1169,6 +1169,6 @@ Item * ...@@ -1169,6 +1169,6 @@ Item *
sp_prepare_func_item(THD* thd, Item **it_addr); sp_prepare_func_item(THD* thd, Item **it_addr);
bool bool
sp_eval_expr(THD *thd, Field *result_field, Item *expr_item); sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr);
#endif /* _SP_HEAD_H_ */ #endif /* _SP_HEAD_H_ */
...@@ -150,7 +150,7 @@ sp_rcontext::init_var_items() ...@@ -150,7 +150,7 @@ sp_rcontext::init_var_items()
bool bool
sp_rcontext::set_return_value(THD *thd, Item *return_value_item) sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{ {
DBUG_ASSERT(m_return_value_fld); DBUG_ASSERT(m_return_value_fld);
...@@ -279,14 +279,14 @@ sp_rcontext::pop_cursors(uint count) ...@@ -279,14 +279,14 @@ sp_rcontext::pop_cursors(uint count)
int int
sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value) sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value)
{ {
return set_variable(thd, m_var_table->field[var_idx], value); return set_variable(thd, m_var_table->field[var_idx], value);
} }
int int
sp_rcontext::set_variable(THD *thd, Field *field, Item *value) sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
{ {
if (!value) if (!value)
{ {
...@@ -478,9 +478,10 @@ sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type) ...@@ -478,9 +478,10 @@ sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type)
*/ */
int int
sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item) sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr)
{ {
if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item))) Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
if (!case_expr_item)
return TRUE; return TRUE;
if (!m_case_expr_holders[case_expr_id] || if (!m_case_expr_holders[case_expr_id] ||
...@@ -542,7 +543,7 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items) ...@@ -542,7 +543,7 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items)
*/ */
for (; spvar= spvar_iter++, item= item_iter++; ) for (; spvar= spvar_iter++, item= item_iter++; )
{ {
if (thd->spcont->set_variable(thd, spvar->offset, item)) if (thd->spcont->set_variable(thd, spvar->offset, &item))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
......
...@@ -91,7 +91,7 @@ class sp_rcontext : public Sql_alloc ...@@ -91,7 +91,7 @@ class sp_rcontext : public Sql_alloc
~sp_rcontext(); ~sp_rcontext();
int int
set_variable(THD *thd, uint var_idx, Item *value); set_variable(THD *thd, uint var_idx, Item **value);
Item * Item *
get_item(uint var_idx); get_item(uint var_idx);
...@@ -100,7 +100,7 @@ class sp_rcontext : public Sql_alloc ...@@ -100,7 +100,7 @@ class sp_rcontext : public Sql_alloc
get_item_addr(uint var_idx); get_item_addr(uint var_idx);
bool bool
set_return_value(THD *thd, Item *return_value_item); set_return_value(THD *thd, Item **return_value_item);
inline bool inline bool
is_return_value_set() const is_return_value_set() const
...@@ -200,7 +200,7 @@ class sp_rcontext : public Sql_alloc ...@@ -200,7 +200,7 @@ class sp_rcontext : public Sql_alloc
*/ */
int int
set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item); set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
Item * Item *
get_case_expr(int case_expr_id); get_case_expr(int case_expr_id);
...@@ -254,7 +254,7 @@ class sp_rcontext : public Sql_alloc ...@@ -254,7 +254,7 @@ class sp_rcontext : public Sql_alloc
Item_cache *create_case_expr_holder(THD *thd, Item_result result_type); Item_cache *create_case_expr_holder(THD *thd, Item_result result_type);
int set_variable(THD *thd, Field *field, Item *value); int set_variable(THD *thd, Field *field, Item **value);
}; // class sp_rcontext : public Sql_alloc }; // class sp_rcontext : public Sql_alloc
......
...@@ -617,118 +617,110 @@ static inline uint tmpkeyval(THD *thd, TABLE *table) ...@@ -617,118 +617,110 @@ static inline uint tmpkeyval(THD *thd, TABLE *table)
void close_temporary_tables(THD *thd) void close_temporary_tables(THD *thd)
{ {
TABLE *next, TABLE *table;
*prev_table /* prev link is not maintained in TABLE's double-linked list */,
*table;
char *query= (gptr) 0, *end;
uint query_buf_size, max_names_len;
bool found_user_tables;
if (!thd->temporary_tables) if (!thd->temporary_tables)
return; return;
LINT_INIT(end);
query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
/* if (!mysql_bin_log.is_open())
insertion sort of temp tables by pseudo_thread_id to build ordered list {
for (table= thd->temporary_tables; table; table= table->next)
{
close_temporary(table, 1);
}
thd->temporary_tables= 0;
return;
}
TABLE *next,
*prev_table /* prev link is not maintained in TABLE's double-linked list */;
bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */
// Better add "if exists", in case a RESET MASTER has been done
const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ";
uint stub_len= sizeof(stub) - 1;
char buf[256];
memcpy(buf, stub, stub_len);
String s_query= String(buf, sizeof(buf), system_charset_info);
bool found_user_tables= false;
LINT_INIT(next);
/*
insertion sort of temp tables by pseudo_thread_id to build ordered list
of sublists of equal pseudo_thread_id of sublists of equal pseudo_thread_id
*/ */
for (prev_table= thd->temporary_tables,
table= prev_table->next, for (prev_table= thd->temporary_tables, table= prev_table->next;
found_user_tables= (prev_table->s->table_name[0] != '#');
table; table;
prev_table= table, table= table->next) prev_table= table, table= table->next)
{ {
TABLE *prev_sorted /* same as for prev_table */, TABLE *prev_sorted /* same as for prev_table */, *sorted;
*sorted; if (is_user_table(table))
/*
table not created directly by the user is moved to the tail.
Fixme/todo: nothing (I checked the manual) prevents user to create temp
with `#'
*/
if (table->s->table_name[0] == '#')
continue;
else
{
found_user_tables = 1;
}
for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
prev_sorted= sorted, sorted= sorted->next)
{ {
if (sorted->s->table_name[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) if (!found_user_tables)
found_user_tables= true;
for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
prev_sorted= sorted, sorted= sorted->next)
{ {
/* move into the sorted part of the list from the unsorted */ if (!is_user_table(sorted) ||
prev_table->next= table->next; tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
table->next= sorted;
if (prev_sorted)
{ {
prev_sorted->next= table; /* move into the sorted part of the list from the unsorted */
} prev_table->next= table->next;
else table->next= sorted;
{ if (prev_sorted)
thd->temporary_tables= table; {
prev_sorted->next= table;
}
else
{
thd->temporary_tables= table;
}
table= prev_table;
break;
} }
table= prev_table;
break;
} }
} }
} }
/*
calc query_buf_size as max per sublists, one sublist per pseudo thread id. /* We always quote db,table names though it is slight overkill */
Also stop at first occurence of `#'-named table that starts if (found_user_tables &&
all implicitly created temp tables !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE)))
*/
for (max_names_len= 0, table=thd->temporary_tables;
table && table->s->table_name[0] != '#';
table=table->next)
{ {
uint tmp_names_len; thd->options |= OPTION_QUOTE_SHOW_CREATE;
for (tmp_names_len= table->s->key_length + 1;
table->next && table->s->table_name[0] != '#' &&
tmpkeyval(thd, table) == tmpkeyval(thd, table->next);
table=table->next)
{
/*
We are going to add 4 ` around the db/table names, so 1 might not look
enough; indeed it is enough, because table->key_length is greater (by 8,
because of server_id and thread_id) than db||table.
*/
tmp_names_len += table->next->s->key_length + 1;
}
if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
} }
/* allocate */
if (found_user_tables && mysql_bin_log.is_open() &&
(query = alloc_root(thd->mem_root, query_buf_size+= max_names_len)))
// Better add "if exists", in case a RESET MASTER has been done
end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
/* scan sorted tmps to generate sequence of DROP */ /* scan sorted tmps to generate sequence of DROP */
for (table=thd->temporary_tables; table; table= next) for (table= thd->temporary_tables; table; table= next)
{ {
if (query // we might be out of memory, but this is not fatal if (is_user_table(table))
&& table->s->table_name[0] != '#')
{ {
char *end_cur;
/* Set pseudo_thread_id to be that of the processed table */ /* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table); thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
/* Loop forward through all tables within the sublist of /* Loop forward through all tables within the sublist of
common pseudo_thread_id to create single DROP query */ common pseudo_thread_id to create single DROP query */
for (end_cur= end; for (s_query.length(stub_len);
table && table->s->table_name[0] != '#' && table && is_user_table(table) &&
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id; tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
table= next) table= next)
{ {
end_cur= strxmov(end_cur, "`", table->s->db, "`.`", /*
table->s->table_name, "`,", NullS); We are going to add 4 ` around the db/table names and possible more
due to special characters in the names
*/
append_identifier(thd, &s_query, table->s->db, strlen(table->s->db));
s_query.q_append('.');
append_identifier(thd, &s_query, table->s->table_name,
strlen(table->s->table_name));
s_query.q_append(',');
next= table->next; next= table->next;
close_temporary(table, 1); close_temporary(table, 1);
} }
thd->clear_error(); thd->clear_error();
/* The -1 is to remove last ',' */ CHARSET_INFO *cs_save= thd->variables.character_set_client;
Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE); thd->variables.character_set_client= system_charset_info;
Query_log_event qinfo(thd, s_query.ptr(),
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE);
thd->variables.character_set_client= cs_save;
/* /*
Imagine the thread had created a temp table, then was doing a SELECT, and Imagine the thread had created a temp table, then was doing a SELECT, and
the SELECT was killed. Then it's not clever to mark the statement above as the SELECT was killed. Then it's not clever to mark the statement above as
...@@ -741,12 +733,14 @@ void close_temporary_tables(THD *thd) ...@@ -741,12 +733,14 @@ void close_temporary_tables(THD *thd)
qinfo.error_code= 0; qinfo.error_code= 0;
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
else else
{ {
next= table->next; next= table->next;
close_temporary(table, 1); close_temporary(table, 1);
} }
} }
if (!was_quote_show)
thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
thd->temporary_tables=0; thd->temporary_tables=0;
} }
......
...@@ -1877,7 +1877,7 @@ bool select_dumpvar::send_data(List<Item> &items) ...@@ -1877,7 +1877,7 @@ bool select_dumpvar::send_data(List<Item> &items)
if ((yy=var_li++)) if ((yy=var_li++))
{ {
if (thd->spcont->set_variable(current_thd, yy->get_var_idx(), if (thd->spcont->set_variable(current_thd, yy->get_var_idx(),
*it.ref())) it.ref()))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment