summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.local>2006-11-29 11:44:37 +0300
committerunknown <kostja@bodhi.local>2006-11-29 11:44:37 +0300
commit0e978328ae3055a55f9e21cc7b395cf2581925b9 (patch)
treef6410b9231112e66043c0eb7edc1b33fbff6e760 /sql
parent0534b679b70d34db1a9ff3d5ae0c6dd39560636f (diff)
parentfe99bda872fd51b07e1ebb0dc506e26d195edec7 (diff)
downloadmariadb-git-0e978328ae3055a55f9e21cc7b395cf2581925b9.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into bodhi.local:/opt/local/work/mysql-5.1-runtime-merge libmysql/libmysql.c: Auto merged mysql-test/r/ps.result: Auto merged mysql-test/t/func_str.test: Auto merged mysql-test/t/ps.test: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_sum.cc: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_yacc.yy: Auto merged server-tools/instance-manager/mysql_connection.cc: Rollback Monty's removals of explicit casts tests/mysql_client_test.c: SCCS merged
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt1
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/event_data_objects.cc83
-rw-r--r--sql/event_data_objects.h4
-rw-r--r--sql/event_db_repository.cc2
-rw-r--r--sql/event_queue.cc46
-rw-r--r--sql/event_scheduler.cc23
-rw-r--r--sql/events.cc2
-rw-r--r--sql/field.cc364
-rw-r--r--sql/field.h14
-rw-r--r--sql/field_conv.cc12
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/ha_ndbcluster.cc135
-rw-r--r--sql/ha_ndbcluster_binlog.cc123
-rw-r--r--sql/ha_ndbcluster_tables.h2
-rw-r--r--sql/ha_partition.cc10
-rw-r--r--sql/handler.cc51
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h12
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_strfunc.cc6
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_sum.cc34
-rw-r--r--sql/item_timefunc.cc16
-rw-r--r--sql/item_xmlfunc.cc16
-rw-r--r--sql/key.cc51
-rw-r--r--sql/log.cc53
-rw-r--r--sql/log_event.cc240
-rw-r--r--sql/log_event.h22
-rw-r--r--sql/mysql_priv.h16
-rw-r--r--sql/mysqld.cc18
-rw-r--r--sql/mysqld.cc.rej17
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/opt_range.cc20
-rw-r--r--sql/parse_file.cc23
-rw-r--r--sql/parse_file.h17
-rw-r--r--sql/repl_failsafe.cc6
-rw-r--r--sql/rpl_injector.cc2
-rw-r--r--sql/rpl_mi.cc386
-rw-r--r--sql/rpl_mi.h110
-rw-r--r--sql/rpl_rli.cc1112
-rw-r--r--sql/rpl_rli.h29
-rw-r--r--sql/rpl_tblmap.cc16
-rw-r--r--sql/rpl_utility.cc11
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/slave.cc1539
-rw-r--r--sql/slave.h117
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_base.cc25
-rw-r--r--sql/sql_binlog.cc32
-rw-r--r--sql/sql_cache.cc89
-rw-r--r--sql/sql_class.cc256
-rw-r--r--sql/sql_class.h11
-rw-r--r--sql/sql_db.cc46
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_handler.cc7
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_parse.cc361
-rw-r--r--sql/sql_parse.cc.rej166
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_prepare.cc22
-rw-r--r--sql/sql_repl.cc20
-rw-r--r--sql/sql_select.cc16
-rw-r--r--sql/sql_show.cc3
-rw-r--r--sql/sql_string.cc156
-rw-r--r--sql/sql_string.h8
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_test.cc9
-rw-r--r--sql/sql_trigger.cc4
-rw-r--r--sql/sql_update.cc4
-rw-r--r--sql/sql_view.cc35
-rw-r--r--sql/sql_yacc.yy38
-rw-r--r--sql/strfunc.cc2
-rw-r--r--sql/table.cc68
-rw-r--r--sql/table.cc.rej17
-rw-r--r--sql/tztime.cc15
-rw-r--r--sql/unireg.cc8
80 files changed, 3523 insertions, 2696 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 1c2944de530..4cdc4c01c4e 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -54,6 +54,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
event_queue.cc event_db_repository.cc
sql_tablespace.cc events.cc ../sql-common/my_user.c
partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
+ rpl_rli.cc rpl_mi.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 9a0303a433f..ac2f4836c15 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -54,7 +54,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
ha_ndbcluster.h ha_ndbcluster_binlog.h \
ha_ndbcluster_tables.h \
opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
- log.h sql_show.h rpl_rli.h \
+ log.h sql_show.h rpl_rli.h rpl_mi.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h \
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h sql_repl.h slave.h rpl_filter.h \
@@ -94,7 +94,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \
- rpl_utility.cc rpl_injector.cc \
+ rpl_utility.cc rpl_injector.cc rpl_rli.cc rpl_mi.cc \
sql_union.cc sql_derived.cc \
client.c sql_client.cc mini_client_errors.c pack.c\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index afd10350bb5..0de90e4145b 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -124,8 +124,8 @@ void
Event_parse_data::init_body(THD *thd)
{
DBUG_ENTER("Event_parse_data::init_body");
- DBUG_PRINT("info", ("body=[%s] body_begin=0x%lx end=0x%lx", body_begin,
- body_begin, thd->lex->ptr));
+ DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin,
+ (long) body_begin, (long) thd->lex->ptr));
body.length= thd->lex->ptr - body_begin;
const uchar *body_end= body_begin + body.length - 1;
@@ -399,8 +399,9 @@ Event_parse_data::init_starts(THD *thd)
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
(my_time_t) thd->query_start());
- DBUG_PRINT("info",("now =%lld", TIME_to_ulonglong_datetime(&time_tmp)));
- DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(&ltime)));
+ DBUG_PRINT("info",("now: %ld starts: %ld",
+ (long) TIME_to_ulonglong_datetime(&time_tmp),
+ (long) TIME_to_ulonglong_datetime(&ltime)));
if (TIME_to_ulonglong_datetime(&ltime) <
TIME_to_ulonglong_datetime(&time_tmp))
goto wrong_value;
@@ -536,8 +537,9 @@ Event_parse_data::check_parse_data(THD *thd)
{
bool ret;
DBUG_ENTER("Event_parse_data::check_parse_data");
- DBUG_PRINT("info", ("execute_at=0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
- item_execute_at, item_expression, item_starts, item_ends));
+ DBUG_PRINT("info", ("execute_at: 0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
+ (long) item_execute_at, (long) item_expression,
+ (long) item_starts, (long) item_ends));
init_name(thd, identifier);
@@ -564,9 +566,9 @@ Event_parse_data::init_definer(THD *thd)
int definer_host_len;
DBUG_ENTER("Event_parse_data::init_definer");
- DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx "
- "thd->sec_ctx->priv_user=0x%lx", thd->mem_root,
- thd->security_ctx->priv_user));
+ DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx "
+ "thd->sec_ctx->priv_user: 0x%lx", (long) thd->mem_root,
+ (long) thd->security_ctx->priv_user));
definer_user_len= strlen(thd->security_ctx->priv_user);
definer_host_len= strlen(thd->security_ctx->priv_host);
@@ -1032,8 +1034,9 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
TIME tmp;
longlong months=0, seconds=0;
DBUG_ENTER("get_next_time");
- DBUG_PRINT("enter", ("start=%llu now=%llu", TIME_to_ulonglong_datetime(start),
- TIME_to_ulonglong_datetime(time_now)));
+ DBUG_PRINT("enter", ("start: %lu now: %lu",
+ (long) TIME_to_ulonglong_datetime(start),
+ (long) TIME_to_ulonglong_datetime(time_now)));
bzero(&interval, sizeof(interval));
@@ -1081,7 +1084,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
case INTERVAL_LAST:
DBUG_ASSERT(0);
}
- DBUG_PRINT("info", ("seconds=%ld months=%ld", seconds, months));
+ DBUG_PRINT("info", ("seconds: %ld months: %ld", (long) seconds, (long) months));
if (seconds)
{
longlong seconds_diff;
@@ -1099,14 +1102,14 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
event two times for the same time
get the next exec if the modulus is not
*/
- DBUG_PRINT("info", ("multiplier=%d", multiplier));
+ DBUG_PRINT("info", ("multiplier: %d", multiplier));
if (seconds_diff % seconds || (!seconds_diff && last_exec->year) ||
TIME_to_ulonglong_datetime(time_now) ==
TIME_to_ulonglong_datetime(last_exec))
++multiplier;
interval.second= seconds * multiplier;
- DBUG_PRINT("info", ("multiplier=%u interval.second=%u", multiplier,
- interval.second));
+ DBUG_PRINT("info", ("multiplier: %lu interval.second: %lu", (ulong) multiplier,
+ (ulong) interval.second));
tmp= *start;
if (!(ret= date_add_interval(&tmp, INTERVAL_SECOND, interval)))
*next= tmp;
@@ -1158,7 +1161,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
}
done:
- DBUG_PRINT("info", ("next=%llu", TIME_to_ulonglong_datetime(next)));
+ DBUG_PRINT("info", ("next: %lu", (long) TIME_to_ulonglong_datetime(next)));
DBUG_RETURN(ret);
}
@@ -1183,17 +1186,17 @@ Event_queue_element::compute_next_execution_time()
{
TIME time_now;
int tmp;
-
DBUG_ENTER("Event_queue_element::compute_next_execution_time");
- DBUG_PRINT("enter", ("starts=%llu ends=%llu last_executed=%llu this=0x%lx",
- TIME_to_ulonglong_datetime(&starts),
- TIME_to_ulonglong_datetime(&ends),
- TIME_to_ulonglong_datetime(&last_executed), this));
+ DBUG_PRINT("enter", ("starts: %lu ends: %lu last_executed: %lu this: 0x%lx",
+ (long) TIME_to_ulonglong_datetime(&starts),
+ (long) TIME_to_ulonglong_datetime(&ends),
+ (long) TIME_to_ulonglong_datetime(&last_executed),
+ (long) this));
if (status == Event_queue_element::DISABLED)
{
DBUG_PRINT("compute_next_execution_time",
- ("Event %s is DISABLED", name.str));
+ ("Event %s is DISABLED", name.str));
goto ret;
}
/* If one-time, no need to do computation */
@@ -1203,9 +1206,9 @@ Event_queue_element::compute_next_execution_time()
if (last_executed.year)
{
DBUG_PRINT("info",("One-time event %s.%s of was already executed",
- dbname.str, name.str, definer.str));
+ dbname.str, name.str));
dropped= (on_completion == Event_queue_element::ON_COMPLETION_DROP);
- DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped));
+ DBUG_PRINT("info",("One-time event will be dropped: %d.", dropped));
status= Event_queue_element::DISABLED;
status_changed= TRUE;
@@ -1215,7 +1218,8 @@ Event_queue_element::compute_next_execution_time()
my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start());
- DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now)));
+ DBUG_PRINT("info",("NOW: [%lu]",
+ (ulong) TIME_to_ulonglong_datetime(&time_now)));
/* if time_now is after ends don't execute anymore */
if (!ends_null && (tmp= my_time_compare(&ends, &time_now)) == -1)
@@ -1226,7 +1230,7 @@ Event_queue_element::compute_next_execution_time()
execute_at_null= TRUE;
if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
dropped= TRUE;
- DBUG_PRINT("info", ("Dropped=%d", dropped));
+ DBUG_PRINT("info", ("Dropped: %d", dropped));
status= Event_queue_element::DISABLED;
status_changed= TRUE;
@@ -1297,7 +1301,8 @@ Event_queue_element::compute_next_execution_time()
}
else
{
- DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec)));
+ DBUG_PRINT("info",("Next[%lu]",
+ (ulong) TIME_to_ulonglong_datetime(&next_exec)));
execute_at= next_exec;
execute_at_null= FALSE;
}
@@ -1319,7 +1324,8 @@ Event_queue_element::compute_next_execution_time()
expression, interval))
goto err;
execute_at= next_exec;
- DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec)));
+ DBUG_PRINT("info",("Next[%lu]",
+ (ulong) TIME_to_ulonglong_datetime(&next_exec)));
}
else
{
@@ -1353,7 +1359,8 @@ Event_queue_element::compute_next_execution_time()
expression, interval))
goto err;
execute_at= next_exec;
- DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec)));
+ DBUG_PRINT("info",("Next[%lu]",
+ (ulong) TIME_to_ulonglong_datetime(&next_exec)));
}
execute_at_null= FALSE;
}
@@ -1390,8 +1397,8 @@ Event_queue_element::compute_next_execution_time()
}
else
{
- DBUG_PRINT("info", ("Next[%llu]",
- TIME_to_ulonglong_datetime(&next_exec)));
+ DBUG_PRINT("info", ("Next[%lu]",
+ (ulong) TIME_to_ulonglong_datetime(&next_exec)));
execute_at= next_exec;
execute_at_null= FALSE;
}
@@ -1400,8 +1407,8 @@ Event_queue_element::compute_next_execution_time()
goto ret;
}
ret:
- DBUG_PRINT("info", ("ret=0 execute_at=%llu",
- TIME_to_ulonglong_datetime(&execute_at)));
+ DBUG_PRINT("info", ("ret: 0 execute_at: %lu",
+ (long) TIME_to_ulonglong_datetime(&execute_at)));
DBUG_RETURN(FALSE);
err:
DBUG_PRINT("info", ("ret=1"));
@@ -1688,7 +1695,7 @@ done:
thd->end_statement();
thd->cleanup_after_query();
- DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
+ DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret));
DBUG_RETURN(ret);
}
@@ -1752,7 +1759,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
thd->update_charset();
- DBUG_PRINT("info",("old_sql_mode=%d new_sql_mode=%d",old_sql_mode, sql_mode));
+ DBUG_PRINT("info",("old_sql_mode: %lu new_sql_mode: %lu",old_sql_mode, sql_mode));
thd->variables.sql_mode= this->sql_mode;
/* Change the memory root for the execution time */
if (mem_root)
@@ -1769,7 +1776,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
thd->query= show_create.c_ptr_safe();
thd->query_length= show_create.length();
- DBUG_PRINT("info", ("query:%s",thd->query));
+ DBUG_PRINT("info", ("query: %s",thd->query));
event_change_security_context(thd, definer_user, definer_host, dbname,
&save_ctx);
@@ -1777,14 +1784,14 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
mysql_init_query(thd, (uchar*) thd->query, thd->query_length);
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
{
- DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d",
+ DBUG_PRINT("error", ("error during compile or thd->is_fatal_error: %d",
thd->is_fatal_error));
/*
Free lex associated resources
QQ: Do we really need all this stuff here?
*/
sql_print_error("SCHEDULER: Error during compilation of %s.%s or "
- "thd->is_fatal_error=%d",
+ "thd->is_fatal_error: %d",
dbname.str, name.str, thd->is_fatal_error);
lex.unit.cleanup();
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index e7e96d299fb..2da39c2158b 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -111,14 +111,14 @@ public:
void *p;
DBUG_ENTER("Event_queue_element::new(size)");
p= my_malloc(size, MYF(0));
- DBUG_PRINT("info", ("alloc_ptr=0x%lx", p));
+ DBUG_PRINT("info", ("alloc_ptr: 0x%lx", (long) p));
DBUG_RETURN(p);
}
static void operator delete(void *ptr, size_t size)
{
DBUG_ENTER("Event_queue_element::delete(ptr,size)");
- DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr));
+ DBUG_PRINT("enter", ("free_ptr: 0x%lx", (long) ptr));
TRASH(ptr, size);
my_free((gptr) ptr, MYF(0));
DBUG_VOID_RETURN;
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 3d30aff669b..367c5bae579 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -958,7 +958,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
Open_tables_state backup;
DBUG_ENTER("Event_db_repository::load_named_event");
- DBUG_PRINT("enter",("thd=0x%lx name:%*s",thd, name.length, name.str));
+ DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, name.length, name.str));
thd->reset_n_backup_open_tables_state(&backup);
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 527a59018a8..7ec665fcd5f 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -143,7 +143,7 @@ Event_queue::init_queue(THD *thd, Event_db_repository *db_repo)
struct event_queue_param *event_queue_param_value= NULL;
DBUG_ENTER("Event_queue::init_queue");
- DBUG_PRINT("enter", ("this=0x%lx", this));
+ DBUG_PRINT("enter", ("this: 0x%lx", (long) this));
LOCK_QUEUE_DATA();
db_repository= db_repo;
@@ -218,7 +218,7 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
int res;
Event_queue_element *new_element;
DBUG_ENTER("Event_queue::create_event");
- DBUG_PRINT("enter", ("thd=0x%lx et=%s.%s",thd, dbname.str, name.str));
+ DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd, dbname.str, name.str));
new_element= new Event_queue_element();
res= db_repository->load_named_event(thd, dbname, name, new_element);
@@ -229,7 +229,7 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
new_element->compute_next_execution_time();
LOCK_QUEUE_DATA();
- DBUG_PRINT("info", ("new event in the queue 0x%lx", new_element));
+ DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
queue_insert_safe(&queue, (byte *) new_element);
dbug_dump_queue(thd->query_start());
pthread_cond_broadcast(&COND_queue_state);
@@ -264,7 +264,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
Event_queue_element *new_element;
DBUG_ENTER("Event_queue::update_event");
- DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str));
+ DBUG_PRINT("enter", ("thd: 0x%lx et=[%s.%s]", (long) thd, dbname.str, name.str));
new_element= new Event_queue_element();
@@ -294,7 +294,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
/* If not disabled event */
if (new_element)
{
- DBUG_PRINT("info", ("new event in the Q 0x%lx", new_element));
+ DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
queue_insert_safe(&queue, (byte *) new_element);
pthread_cond_broadcast(&COND_queue_state);
}
@@ -322,7 +322,8 @@ void
Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
{
DBUG_ENTER("Event_queue::drop_event");
- DBUG_PRINT("enter", ("thd=0x%lx db=%s name=%s", thd, dbname.str, name.str));
+ DBUG_PRINT("enter", ("thd: 0x%lx db :%s name: %s", (long) thd,
+ dbname.str, name.str));
LOCK_QUEUE_DATA();
find_n_remove_event(dbname, name);
@@ -484,7 +485,7 @@ Event_queue::load_events_from_db(THD *thd)
bool clean_the_queue= TRUE;
DBUG_ENTER("Event_queue::load_events_from_db");
- DBUG_PRINT("enter", ("thd=0x%lx", thd));
+ DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
{
@@ -555,7 +556,6 @@ Event_queue::load_events_from_db(THD *thd)
goto end;
}
- DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list."));
queue_insert_safe(&queue, (byte *) et);
count++;
}
@@ -663,16 +663,20 @@ Event_queue::dbug_dump_queue(time_t now)
for (i = 0; i < queue.elements; i++)
{
et= ((Event_queue_element*)queue_element(&queue, i));
- DBUG_PRINT("info",("et=0x%lx db=%s name=%s",et, et->dbname.str, et->name.str));
- DBUG_PRINT("info", ("exec_at=%llu starts=%llu ends=%llu execs_so_far=%u"
- " expr=%lld et.exec_at=%d now=%d (et.exec_at - now)=%d if=%d",
- TIME_to_ulonglong_datetime(&et->execute_at),
- TIME_to_ulonglong_datetime(&et->starts),
- TIME_to_ulonglong_datetime(&et->ends),
- et->execution_count,
- et->expression, sec_since_epoch_TIME(&et->execute_at), now,
- (int)(sec_since_epoch_TIME(&et->execute_at) - now),
- sec_since_epoch_TIME(&et->execute_at) <= now));
+ DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et,
+ et->dbname.str, et->name.str));
+ DBUG_PRINT("info", ("exec_at: %lu starts: %lu ends: %lu execs_so_far: %u "
+ "expr: %ld et.exec_at: %ld now: %ld "
+ "(et.exec_at - now): %d if: %d",
+ (long) TIME_to_ulonglong_datetime(&et->execute_at),
+ (long) TIME_to_ulonglong_datetime(&et->starts),
+ (long) TIME_to_ulonglong_datetime(&et->ends),
+ et->execution_count,
+ (long) et->expression,
+ (long) (sec_since_epoch_TIME(&et->execute_at)),
+ (long) now,
+ (int) (sec_since_epoch_TIME(&et->execute_at) - now),
+ sec_since_epoch_TIME(&et->execute_at) <= now));
}
DBUG_VOID_RETURN;
#endif
@@ -812,11 +816,11 @@ end:
if (to_free)
delete top;
- DBUG_PRINT("info", ("returning %d. et_new=0x%lx abstime.tv_sec=%d ",
- ret, *job_data, abstime? abstime->tv_sec:0));
+ DBUG_PRINT("info", ("returning %d et_new: 0x%lx abstime.tv_sec: %ld ",
+ ret, (long) *job_data, abstime ? abstime->tv_sec : 0));
if (*job_data)
- DBUG_PRINT("info", ("db=%s name=%s definer=%s", (*job_data)->dbname.str,
+ DBUG_PRINT("info", ("db: %s name: %s definer=%s", (*job_data)->dbname.str,
(*job_data)->name.str, (*job_data)->definer.str));
DBUG_RETURN(ret);
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 6f9f6887c12..9be2f2d1125 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -264,8 +264,9 @@ event_worker_thread(void *arg)
if (!post_init_event_thread(thd))
{
- DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
- "THD=0x%lx", time(NULL), thd));
+ DBUG_PRINT("info", ("Baikonur, time is %ld, BURAN reporting and operational."
+ "THD: 0x%lx",
+ (long) time(NULL), (long) thd));
sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu. "
"Execution %u",
@@ -378,7 +379,7 @@ Event_scheduler::start()
DBUG_ENTER("Event_scheduler::start");
LOCK_DATA();
- DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state]));
+ DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state].str));
if (state > INITIALIZED)
goto end;
@@ -400,7 +401,7 @@ Event_scheduler::start()
scheduler_thd= new_thd;
DBUG_PRINT("info", ("Setting state go RUNNING"));
state= RUNNING;
- DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
+ DBUG_PRINT("info", ("Forking new thread for scheduduler. THD: 0x%lx", (long) new_thd));
if (pthread_create(&th, &connection_attrib, event_scheduler_thread,
(void*)scheduler_param_value))
{
@@ -463,7 +464,7 @@ Event_scheduler::run(THD *thd)
break;
}
- DBUG_PRINT("info", ("get_top returned job_data=0x%lx", job_data));
+ DBUG_PRINT("info", ("get_top returned job_data: 0x%lx", (long) job_data));
if (job_data)
{
if ((res= execute_top(thd, job_data)))
@@ -522,11 +523,11 @@ Event_scheduler::execute_top(THD *thd, Event_job_data *job_data)
++started_events;
- DBUG_PRINT("info", ("Launch succeeded. BURAN is in THD=0x%lx", new_thd));
+ DBUG_PRINT("info", ("Launch succeeded. BURAN is in THD: 0x%lx", (long) new_thd));
DBUG_RETURN(FALSE);
error:
- DBUG_PRINT("error", ("Baikonur, we have a problem! res=%d", res));
+ DBUG_PRINT("error", ("Baikonur, we have a problem! res: %d", res));
if (new_thd)
{
new_thd->proc_info= "Clearing";
@@ -581,10 +582,10 @@ Event_scheduler::stop()
{
THD *thd= current_thd;
DBUG_ENTER("Event_scheduler::stop");
- DBUG_PRINT("enter", ("thd=0x%lx", current_thd));
+ DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
LOCK_DATA();
- DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state]));
+ DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state].str));
if (state != RUNNING)
goto end;
@@ -605,7 +606,7 @@ Event_scheduler::stop()
*/
state= STOPPING;
- DBUG_PRINT("info", ("Manager thread has id %d", scheduler_thd->thread_id));
+ DBUG_PRINT("info", ("Manager thread has id %lu", scheduler_thd->thread_id));
/* Lock from delete */
pthread_mutex_lock(&scheduler_thd->LOCK_delete);
/* This will wake up the thread if it waits on Queue's conditional */
@@ -775,7 +776,7 @@ Event_scheduler::dump_internal_status()
mutex_last_unlocked_at_line);
printf("WOC : %s\n", waiting_on_cond? "YES":"NO");
printf("Workers : %u\n", workers_count());
- printf("Executed : %llu\n", started_events);
+ printf("Executed : %lu\n", (ulong) started_events);
printf("Data locked: %s\n", mutex_scheduler_data_locked ? "YES":"NO");
DBUG_VOID_RETURN;
diff --git a/sql/events.cc b/sql/events.cc
index 10a8be948ef..3dbc6fd27e1 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -858,7 +858,7 @@ Events::check_system_tables(THD *thd)
bool ret= FALSE;
DBUG_ENTER("Events::check_system_tables");
- DBUG_PRINT("enter", ("thd=0x%lx", thd));
+ DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
thd->reset_n_backup_open_tables_state(&backup);
diff --git a/sql/field.cc b/sql/field.cc
index 122a44305f2..1551b78bd72 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1237,12 +1237,6 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
}
-uint Field::offset()
-{
- return (uint) (ptr - (char*) table->record[0]);
-}
-
-
void Field::hash(ulong *nr, ulong *nr2)
{
if (is_null())
@@ -1427,6 +1421,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
field_charset=charset;
if (charset->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
+ field_derivation= DERIVATION_IMPLICIT;
}
@@ -5921,38 +5916,149 @@ void Field_datetime::sql_type(String &res) const
** A string may be varchar or binary
****************************************************************************/
+/*
+ Report "not well formed" or "cannot convert" error
+ after storing a character string info a field.
+
+ SYNOPSIS
+ check_string_copy_error()
+ field - Field
+ well_formed_error_pos - where not well formed data was first met
+ cannot_convert_error_pos - where a not-convertable character was first met
+ end - end of the string
+
+ NOTES
+ As of version 5.0 both cases return the same error:
+
+ "Invalid string value: 'xxx' for column 't' at row 1"
+
+ Future versions will possibly introduce a new error message:
+
+ "Cannot convert character string: 'xxx' for column 't' at row 1"
+
+ RETURN
+ FALSE - If errors didn't happen
+ TRUE - If an error happened
+*/
+
+static bool
+check_string_copy_error(Field_str *field,
+ const char *well_formed_error_pos,
+ const char *cannot_convert_error_pos,
+ const char *end)
+{
+ const char *pos, *end_orig;
+ char tmp[64], *t;
+
+ if (!(pos= well_formed_error_pos) &&
+ !(pos= cannot_convert_error_pos))
+ return FALSE;
+
+ end_orig= end;
+ set_if_smaller(end, pos + 6);
+
+ for (t= tmp; pos < end; pos++)
+ {
+ if (((unsigned char) *pos) >= 0x20 &&
+ ((unsigned char) *pos) <= 0x7F)
+ {
+ *t++= *pos;
+ }
+ else
+ {
+ *t++= '\\';
+ *t++= 'x';
+ *t++= _dig_vec_upper[((unsigned char) *pos) >> 4];
+ *t++= _dig_vec_upper[((unsigned char) *pos) & 15];
+ }
+ }
+ if (end_orig > end)
+ {
+ *t++= '.';
+ *t++= '.';
+ *t++= '.';
+ }
+ *t= '\0';
+ push_warning_printf(field->table->in_use,
+ field->table->in_use->abort_on_warning ?
+ MYSQL_ERROR::WARN_LEVEL_ERROR :
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "string", tmp, field->field_name,
+ (ulong) field->table->in_use->row_count);
+ return TRUE;
+}
+
+
+
+/*
+ Send a truncation warning or a truncation error
+ after storing a too long character string info a field.
+
+ SYNOPSIS
+ report_data_too_long()
+ field - Field
+
+ RETURN
+ N/A
+*/
+
+inline void
+report_data_too_long(Field_str *field)
+{
+ if (field->table->in_use->abort_on_warning)
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+}
+
+
+/*
+ Test if the given string contains important data:
+ not spaces for character string,
+ or any data for binary string.
+
+ SYNOPSIS
+ test_if_important_data()
+ cs Character set
+ str String to test
+ strend String end
+
+ RETURN
+ FALSE - If string does not have important data
+ TRUE - If string has some important data
+*/
+
+static bool
+test_if_important_data(CHARSET_INFO *cs, const char *str, const char *strend)
+{
+ if (cs != &my_charset_bin)
+ str+= cs->cset->scan(cs, str, strend, MY_SEQ_SPACES);
+ return (str < strend);
+}
+
+
/* Copy a string and fill with space */
int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE;
- int error= 0, well_formed_error;
- uint32 not_used;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos;
/* See the comment for Field_long::store(long long) */
DBUG_ASSERT(table->in_use == current_thd);
- /* Convert character set if necessary */
- if (String::needs_conversion(length, cs, field_charset, &not_used))
- {
- uint conv_errors;
- tmpstr.copy(from, length, cs, field_charset, &conv_errors);
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error= 2;
- }
-
- /* Make sure we don't break a multibyte sequence or copy malformed data. */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from+length,
- field_length/
- field_charset->mbmaxlen,
- &well_formed_error);
- memmove(ptr, from, copy_length);
+ copy_length= well_formed_copy_nchars(field_charset,
+ ptr, field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
/* Append spaces if the string was shorter than the field. */
if (copy_length < field_length)
@@ -5960,32 +6066,23 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
field_length-copy_length,
field_charset->pad_char);
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
/*
Check if we lost any important data (anything in a binary string,
or any non-space in others).
*/
- if ((copy_length < length) && table->in_use->count_cuted_fields)
+ if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
- if (binary())
- error= 2;
- else
+ if (test_if_important_data(field_charset, from_end_pos, from + length))
{
- const char *end=from+length;
- from+= copy_length;
- from+= field_charset->cset->scan(field_charset, from, end,
- MY_SEQ_SPACES);
- if (from != end)
- error= 2;
+ report_data_too_long(this);
+ return 2;
}
}
- if (error)
- {
- if (table->in_use->abort_on_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
- else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
- }
- return error;
+ return 0;
}
@@ -6343,58 +6440,35 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE;
- uint32 not_used, copy_length;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
- int error_code= 0, well_formed_error;
- enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN;
+ uint copy_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos;
+
+ copy_length= well_formed_copy_nchars(field_charset,
+ ptr + length_bytes, field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
- /* Convert character set if necessary */
- if (String::needs_conversion(length, cs, field_charset, &not_used))
- {
- uint conv_errors;
- tmpstr.copy(from, length, cs, field_charset, &conv_errors);
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error_code= WARN_DATA_TRUNCATED;
- }
- /*
- Make sure we don't break a multibyte sequence
- as well as don't copy a malformed data.
- */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from+length,
- field_length/
- field_charset->mbmaxlen,
- &well_formed_error);
- memmove(ptr + length_bytes, from, copy_length);
if (length_bytes == 1)
*ptr= (uchar) copy_length;
else
int2store(ptr, copy_length);
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
// Check if we lost something other than just trailing spaces
- if ((copy_length < length) && table->in_use->count_cuted_fields &&
- !error_code)
- {
- if (!binary())
- {
- const char *end= from + length;
- from+= copy_length;
- from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
- /* If we lost only spaces then produce a NOTE, not a WARNING */
- if (from == end)
- level= MYSQL_ERROR::WARN_LEVEL_NOTE;
- }
- error_code= WARN_DATA_TRUNCATED;
- }
- if (error_code)
+ if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
- if (level == MYSQL_ERROR::WARN_LEVEL_WARN &&
- table->in_use->abort_on_warning)
- error_code= ER_DATA_TOO_LONG;
- set_warning(level, error_code, 1);
+ if (test_if_important_data(field_charset, from_end_pos, from + length))
+ report_data_too_long(this);
+ else /* If we lost only spaces then produce a NOTE, not a WARNING */
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
return 2;
}
return 0;
@@ -7012,68 +7086,70 @@ void Field_blob::put_length(char *pos, uint32 length)
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE;
- int error= 0, well_formed_error;
+ uint copy_length, new_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos, *tmp;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
if (!length)
{
bzero(ptr,Field_blob::pack_length());
+ return 0;
}
- else
- {
- bool was_conversion;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
- uint copy_length;
- uint32 not_used;
- /* Convert character set if necessary */
- if ((was_conversion= String::needs_conversion(length, cs, field_charset,
- &not_used)))
- {
- uint conv_errors;
- if (tmpstr.copy(from, length, cs, field_charset, &conv_errors))
- {
- /* Fatal OOM error */
- bzero(ptr,Field_blob::pack_length());
- return -1;
- }
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error= 2;
- }
-
- copy_length= max_data_length();
- /*
- copy_length is OK as last argument to well_formed_len as this is never
- used to limit the length of the data. The cut of long data is done with
- the 'min()' call below.
- */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from +
- min(length, copy_length),
- copy_length,
- &well_formed_error);
- if (copy_length < length)
- error= 2;
- Field_blob::store_length(copy_length);
- if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
- { // Must make a copy
- if (from != value.ptr()) // For valgrind
- {
- value.copy(from,copy_length,charset());
- from=value.ptr();
- }
+ if (from == value.ptr())
+ {
+ uint32 dummy_offset;
+ if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
+ {
+ Field_blob::store_length(length);
+ bmove(ptr+packlength,(char*) &from,sizeof(char*));
+ return 0;
}
- bmove(ptr+packlength,(char*) &from,sizeof(char*));
+ if (tmpstr.copy(from, length, cs))
+ goto oom_error;
+ from= tmpstr.ptr();
}
- if (error)
+
+ new_length= min(max_data_length(), field_charset->mbmaxlen * length);
+ if (value.alloc(new_length))
+ goto oom_error;
+
+ /*
+ "length" is OK as "nchars" argument to well_formed_copy_nchars as this
+ is never used to limit the length of the data. The cut of long data
+ is done with the new_length value.
+ */
+ copy_length= well_formed_copy_nchars(field_charset,
+ (char*) value.ptr(), new_length,
+ cs, from, length,
+ length,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
+
+ Field_blob::store_length(copy_length);
+ tmp= value.ptr();
+ bmove(ptr+packlength,(char*) &tmp,sizeof(char*));
+
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
+ if (copy_length < length)
{
- if (table->in_use->abort_on_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
- else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+ report_data_too_long(this);
+ return 2;
}
+
return 0;
+
+oom_error:
+ /* Fatal OOM error */
+ bzero(ptr,Field_blob::pack_length());
+ return -1;
}
@@ -8104,8 +8180,8 @@ Field_bit::do_last_null_byte() const
bits. On systems with CHAR_BIT > 8 (not very common), the storage
will lose the extra bits.
*/
- DBUG_PRINT("debug", ("bit_ofs=%d, bit_len=%d, bit_ptr=%p",
- bit_ofs, bit_len, bit_ptr));
+ DBUG_PRINT("test", ("bit_ofs: %d, bit_len: %d bit_ptr: 0x%lx",
+ bit_ofs, bit_len, (long) bit_ptr));
uchar *result;
if (bit_len == 0)
result= null_ptr;
diff --git a/sql/field.h b/sql/field.h
index 9b81931d416..433f5c6bfbf 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -239,7 +239,7 @@ public:
*/
my_size_t last_null_byte() const {
my_size_t bytes= do_last_null_byte();
- DBUG_PRINT("debug", ("last_null_byte() ==> %d", bytes));
+ DBUG_PRINT("debug", ("last_null_byte() ==> %ld", (long) bytes));
DBUG_ASSERT(bytes <= table->s->null_bytes);
return bytes;
}
@@ -342,7 +342,10 @@ public:
virtual int pack_cmp(const char *b, uint key_length_arg,
my_bool insert_or_update)
{ return cmp(ptr,b); }
- uint offset(); // Should be inline ...
+ uint offset(byte *record)
+ {
+ return (uint) (ptr - (char*) record);
+ }
void copy_from_tmp(int offset);
uint fill_cache_field(struct st_cache_field *copy);
virtual bool get_date(TIME *ltime,uint fuzzydate);
@@ -351,6 +354,9 @@ public:
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { }
+ virtual enum Derivation derivation(void) const
+ { return DERIVATION_IMPLICIT; }
+ virtual void set_derivation(enum Derivation derivation) { }
bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
int cuted_increment);
bool check_int(const char *str, int length, const char *int_end,
@@ -446,6 +452,7 @@ public:
class Field_str :public Field {
protected:
CHARSET_INFO *field_charset;
+ enum Derivation field_derivation;
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
@@ -459,6 +466,9 @@ public:
uint size_of() const { return sizeof(*this); }
CHARSET_INFO *charset(void) const { return field_charset; }
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
+ enum Derivation derivation(void) const { return field_derivation; }
+ virtual void set_derivation(enum Derivation derivation_arg)
+ { field_derivation= derivation_arg; }
bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_length() { return field_length; }
friend class create_field;
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 7bc6c432d1c..01b5306f5a4 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -119,12 +119,12 @@ set_field_to_null(Field *field)
return 0;
}
field->reset();
- if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
+ if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
{
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
return 0;
}
- if (!current_thd->no_errors)
+ if (!field->table->in_use->no_errors)
my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -176,12 +176,12 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
field->table->auto_increment_field_not_null= FALSE;
return 0; // field is set in handler.cc
}
- if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
+ if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
{
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
return 0;
}
- if (!current_thd->no_errors)
+ if (!field->table->in_use->no_errors)
my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -403,7 +403,7 @@ static void do_varstring1(Copy_field *copy)
if (length > copy->to_length- 1)
{
length=copy->to_length - 1;
- if (current_thd->count_cuted_fields)
+ if (copy->from_field->table->in_use->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
@@ -418,7 +418,7 @@ static void do_varstring2(Copy_field *copy)
if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
{
length=copy->to_length-HA_KEY_BLOB_LENGTH;
- if (current_thd->count_cuted_fields)
+ if (copy->from_field->table->in_use->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 01f3bb97557..2cba2b733da 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -302,7 +302,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
DBUG_POP(); /* Ok to DBUG */
#endif
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
- DBUG_PRINT("exit",("records: %ld",records));
+ DBUG_PRINT("exit",("records: %ld", (long) records));
DBUG_RETURN(error ? HA_POS_ERROR : records);
} /* filesort */
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 9df2171d85c..0703e18b5f7 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -413,7 +413,8 @@ Thd_ndb::get_open_table(THD *thd, const void *key)
thd_ndb_share->stat.no_uncommitted_rows_count= 0;
thd_ndb_share->stat.records= ~(ha_rows)0;
}
- DBUG_PRINT("exit", ("thd_ndb_share: 0x%x key: 0x%x", thd_ndb_share, key));
+ DBUG_PRINT("exit", ("thd_ndb_share: 0x%lx key: 0x%lx",
+ (long) thd_ndb_share, (long) key));
DBUG_RETURN(thd_ndb_share);
}
@@ -761,8 +762,8 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
blob_ptr= (char*)"";
}
- DBUG_PRINT("value", ("set blob ptr=%p len=%u",
- blob_ptr, blob_len));
+ DBUG_PRINT("value", ("set blob ptr: 0x%lx len: %u",
+ (long) blob_ptr, blob_len));
DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26));
if (set_blob_value)
@@ -847,8 +848,8 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array,
uint32 len= 0xffffffff; // Max uint32
if (ndb_blob->readData(buf, len) != 0)
ERR_RETURN(ndb_blob->getNdbError());
- DBUG_PRINT("info", ("[%u] offset=%u buf=%p len=%u [ptrdiff=%d]",
- i, offset, buf, len, (int)ptrdiff));
+ DBUG_PRINT("info", ("[%u] offset: %u buf: 0x%lx len=%u [ptrdiff=%d]",
+ i, offset, (long) buf, len, (int)ptrdiff));
DBUG_ASSERT(len == len64);
// Ugly hack assumes only ptr needs to be changed
field_blob->ptr+= ptrdiff;
@@ -1171,8 +1172,8 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
index= dict->getIndexGlobal(index_name, *m_table);
if (!index)
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
- index,
+ DBUG_PRINT("info", ("index: 0x%lx id: %d version: %d.%d status: %d",
+ (long) index,
index->getObjectId(),
index->getObjectVersion() & 0xFFFFFF,
index->getObjectVersion() >> 24,
@@ -1215,8 +1216,8 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
index= dict->getIndexGlobal(unique_index_name, *m_table);
if (!index)
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
- index,
+ DBUG_PRINT("info", ("index: 0x%lx id: %d version: %d.%d status: %d",
+ (long) index,
index->getObjectId(),
index->getObjectVersion() & 0xFFFFFF,
index->getObjectVersion() >> 24,
@@ -2072,7 +2073,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
all pending update or delete operations should
be sent to NDB
*/
- DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
+ DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending));
if (m_ops_pending)
{
if (m_transaction_on)
@@ -2305,7 +2306,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
// Set bound if not done with this key
if (p.key != NULL)
{
- DBUG_PRINT("info", ("key %d:%d offset=%d length=%d last=%d bound=%d",
+ DBUG_PRINT("info", ("key %d:%d offset: %d length: %d last: %d bound: %d",
j, i, tot_len, part_len, p.part_last, p.bound_type));
DBUG_DUMP("info", (const char*)p.part_ptr, part_store_len);
@@ -2462,7 +2463,7 @@ int ha_ndbcluster::full_table_scan(byte *buf)
part_spec.start_part= 0;
part_spec.end_part= m_part_info->get_tot_partitions() - 1;
prune_partition_set(table, &part_spec);
- DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
+ DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
@@ -2658,7 +2659,7 @@ int ha_ndbcluster::write_row(byte *record)
{
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
- "rows_inserted:%d, bulk_insert_rows: %d",
+ "rows_inserted: %d bulk_insert_rows: %d",
(int)m_rows_inserted, (int)m_bulk_insert_rows));
m_bulk_insert_not_flushed= FALSE;
@@ -3108,7 +3109,8 @@ void ndb_unpack_record(TABLE *table, NdbValue *value,
char* ptr;
field_blob->get_ptr(&ptr, row_offset);
uint32 len= field_blob->get_length(row_offset);
- DBUG_PRINT("info",("[%u] SET ptr=%p len=%u", col_no, ptr, len));
+ DBUG_PRINT("info",("[%u] SET ptr: 0x%lx len: %u",
+ col_no, (long) ptr, len));
#endif
}
}
@@ -3350,7 +3352,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
if (m_use_partition_function)
{
get_partition_set(table, buf, active_index, start_key, &part_spec);
- DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
+ DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
@@ -3480,7 +3482,7 @@ int ha_ndbcluster::close_scan()
Take over any pending transactions to the
deleteing/updating transaction before closing the scan
*/
- DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
+ DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending));
if (execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
@@ -3876,7 +3878,7 @@ int ha_ndbcluster::end_bulk_insert()
NdbTransaction *trans= m_active_trans;
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
- "rows_inserted:%d, bulk_insert_rows: %d",
+ "rows_inserted: %d bulk_insert_rows: %d",
(int) m_rows_inserted, (int) m_bulk_insert_rows));
m_bulk_insert_not_flushed= FALSE;
if (m_transaction_on)
@@ -4286,8 +4288,8 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all)
while ((share= it++))
{
pthread_mutex_lock(&share->mutex);
- DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %d ",
- share->key, share->commit_count));
+ DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %lu",
+ share->table_name, (ulong) share->commit_count));
share->commit_count= 0;
share->commit_count_lock++;
pthread_mutex_unlock(&share->mutex);
@@ -4690,8 +4692,7 @@ int ha_ndbcluster::create(const char *name,
my_free((char*)data, MYF(0));
DBUG_RETURN(2);
}
-
- DBUG_PRINT("info", ("setFrm data=%lx len=%d", pack_data, pack_length));
+ DBUG_PRINT("info", ("setFrm data: 0x%lx len: %d", (long) pack_data, pack_length));
tab.setFrm(pack_data, pack_length);
my_free((char*)data, MYF(0));
my_free((char*)pack_data, MYF(0));
@@ -5102,13 +5103,12 @@ void ha_ndbcluster::prepare_for_alter()
int ha_ndbcluster::add_index(TABLE *table_arg,
KEY *key_info, uint num_of_keys)
{
- DBUG_ENTER("ha_ndbcluster::add_index");
- DBUG_PRINT("info", ("ha_ndbcluster::add_index to table %s",
- table_arg->s->table_name));
int error= 0;
uint idx;
-
+ DBUG_ENTER("ha_ndbcluster::add_index");
+ DBUG_PRINT("enter", ("table %s", table_arg->s->table_name.str));
DBUG_ASSERT(m_share->state == NSS_ALTERED);
+
for (idx= 0; idx < num_of_keys; idx++)
{
KEY *key= key_info + idx;
@@ -6663,7 +6663,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type)
void ha_ndbcluster::print_error(int error, myf errflag)
{
DBUG_ENTER("ha_ndbcluster::print_error");
- DBUG_PRINT("enter", ("error = %d", error));
+ DBUG_PRINT("enter", ("error: %d", error));
if (error == HA_ERR_NO_PARTITION_FOUND)
m_part_info->print_no_partition_found(table);
@@ -7169,16 +7169,16 @@ static void dbug_print_open_tables()
for (uint i= 0; i < ndbcluster_open_tables.records; i++)
{
NDB_SHARE *share= (NDB_SHARE*) hash_element(&ndbcluster_open_tables, i);
- DBUG_PRINT("share",
- ("[%d] 0x%lx key: %s key_length: %d",
- i, share, share->key, share->key_length));
- DBUG_PRINT("share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ DBUG_PRINT("loop",
+ ("[%d] 0x%lx key: %s key_length: %d",
+ i, (long) share, share->key, share->key_length));
+ DBUG_PRINT("loop",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
share->db, share->table_name,
- share->use_count, share->commit_count));
+ share->use_count, (ulong) share->commit_count));
#ifdef HAVE_NDB_BINLOG
if (share->table)
- DBUG_PRINT("share",
+ DBUG_PRINT("loop",
("table->s->db.table_name: %s.%s",
share->table->s->db.str, share->table->s->table_name.str));
#endif
@@ -7331,13 +7331,13 @@ static int rename_share(NDB_SHARE *share, const char *new_key)
share->table_name= share->db + strlen(share->db) + 1;
ha_ndbcluster::set_tabname(new_key, share->table_name);
- DBUG_PRINT("rename_share",
- ("0x%lx key: %s key_length: %d",
- share, share->key, share->key_length));
- DBUG_PRINT("rename_share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ DBUG_PRINT("info",
+ ("share: 0x%lx key: %s key_length: %d",
+ (long) share, share->key, share->key_length));
+ DBUG_PRINT("info",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
share->db, share->table_name,
- share->use_count, share->commit_count));
+ share->use_count, (ulong) share->commit_count));
if (share->table)
{
DBUG_PRINT("rename_share",
@@ -7372,13 +7372,13 @@ NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share)
dbug_print_open_tables();
- DBUG_PRINT("get_share",
- ("0x%lx key: %s key_length: %d",
- share, share->key, share->key_length));
- DBUG_PRINT("get_share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ DBUG_PRINT("info",
+ ("share: 0x%lx key: %s key_length: %d",
+ (long) share, share->key, share->key_length));
+ DBUG_PRINT("info",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
share->db, share->table_name,
- share->use_count, share->commit_count));
+ share->use_count, (ulong) share->commit_count));
pthread_mutex_unlock(&ndbcluster_mutex);
return share;
}
@@ -7472,11 +7472,11 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
DBUG_PRINT("info",
("0x%lx key: %s key_length: %d key: %s",
- share, share->key, share->key_length, key));
+ (long) share, share->key, share->key_length, key));
DBUG_PRINT("info",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
share->db, share->table_name,
- share->use_count, share->commit_count));
+ share->use_count, (ulong) share->commit_count));
if (!have_lock)
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_RETURN(share);
@@ -7486,13 +7486,12 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
void ndbcluster_real_free_share(NDB_SHARE **share)
{
DBUG_ENTER("ndbcluster_real_free_share");
- DBUG_PRINT("real_free_share",
- ("0x%lx key: %s key_length: %d",
- (*share), (*share)->key, (*share)->key_length));
- DBUG_PRINT("real_free_share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ DBUG_PRINT("enter",
+ ("share: 0x%lx key: %s key_length: %d "
+ "db.tablename: %s.%s use_count: %d commit_count: %lu",
+ (long) (*share), (*share)->key, (*share)->key_length,
(*share)->db, (*share)->table_name,
- (*share)->use_count, (*share)->commit_count));
+ (*share)->use_count, (ulong) (*share)->commit_count));
hash_delete(&ndbcluster_open_tables, (byte*) *share);
thr_lock_delete(&(*share)->lock);
@@ -7540,13 +7539,13 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock)
else
{
dbug_print_open_tables();
- DBUG_PRINT("free_share",
- ("0x%lx key: %s key_length: %d",
- *share, (*share)->key, (*share)->key_length));
- DBUG_PRINT("free_share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ DBUG_PRINT("info",
+ ("share: 0x%lx key: %s key_length: %d",
+ (long) *share, (*share)->key, (*share)->key_length));
+ DBUG_PRINT("info",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
(*share)->db, (*share)->table_name,
- (*share)->use_count, (*share)->commit_count));
+ (*share)->use_count, (ulong) (*share)->commit_count));
}
if (!have_lock)
pthread_mutex_unlock(&ndbcluster_mutex);
@@ -7816,7 +7815,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
get_partition_set(table, curr, active_index,
&multi_range_curr->start_key,
&part_spec);
- DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
+ DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
@@ -8182,7 +8181,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
my_thread_init();
DBUG_ENTER("ndb_util_thread");
- DBUG_PRINT("enter", ("ndb_cache_check_time: %d", ndb_cache_check_time));
+ DBUG_PRINT("enter", ("ndb_cache_check_time: %lu", ndb_cache_check_time));
thd= new THD; /* note that contructor of THD uses DBUG_ */
THD_CHECK_SENTRY(thd);
@@ -8270,7 +8269,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
&abstime);
pthread_mutex_unlock(&LOCK_ndb_util_thread);
#ifdef NDB_EXTRA_DEBUG_UTIL_THREAD
- DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %d",
+ DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %lu",
ndb_cache_check_time));
#endif
if (abort_loop)
@@ -8348,8 +8347,8 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
ndb_get_table_statistics(NULL, false, ndb, ndbtab_g.get_table(), &stat) == 0)
{
char buff[22], buff2[22];
- DBUG_PRINT("ndb_util_thread",
- ("Table: %s, commit_count: %llu, rows: %llu",
+ DBUG_PRINT("info",
+ ("Table: %s commit_count: %s rows: %s",
share->key,
llstr(stat.commit_count, buff),
llstr(stat.row_count, buff2)));
@@ -9191,7 +9190,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
if (context->expecting(Item::INT_ITEM))
{
Item_int *int_item= (Item_int *) item;
- DBUG_PRINT("info", ("value %d", int_item->value));
+ DBUG_PRINT("info", ("value %ld", (long) int_item->value));
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
@@ -9214,7 +9213,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE;
break;
case Item::REAL_ITEM:
- DBUG_PRINT("info", ("REAL_ITEM %s"));
+ DBUG_PRINT("info", ("REAL_ITEM"));
if (context->expecting(Item::REAL_ITEM))
{
Item_float *float_item= (Item_float *) item;
@@ -9262,7 +9261,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE;
break;
case Item::DECIMAL_ITEM:
- DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
+ DBUG_PRINT("info", ("DECIMAL_ITEM"));
if (context->expecting(Item::DECIMAL_ITEM))
{
Item_decimal *decimal_item= (Item_decimal *) item;
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index 3dfca5d1bb2..865fa0bde94 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -161,16 +161,16 @@ static void dbug_print_table(const char *info, TABLE *table)
}
DBUG_PRINT("info",
("%s: %s.%s s->fields: %d "
- "reclength: %d rec_buff_length: %d record[0]: %lx "
- "record[1]: %lx",
+ "reclength: %lu rec_buff_length: %u record[0]: 0x%lx "
+ "record[1]: 0x%lx",
info,
table->s->db.str,
table->s->table_name.str,
table->s->fields,
table->s->reclength,
table->s->rec_buff_length,
- table->record[0],
- table->record[1]));
+ (long) table->record[0],
+ (long) table->record[1]));
for (unsigned int i= 0; i < table->s->fields; i++)
{
@@ -180,7 +180,7 @@ static void dbug_print_table(const char *info, TABLE *table)
"ptr: 0x%lx[+%d] null_bit: %u null_ptr: 0x%lx[+%d]",
i,
f->field_name,
- f->flags,
+ (long) f->flags,
(f->flags & PRI_KEY_FLAG) ? "pri" : "attr",
(f->flags & NOT_NULL_FLAG) ? "" : ",nullable",
(f->flags & UNSIGNED_FLAG) ? ",unsigned" : ",signed",
@@ -189,16 +189,18 @@ static void dbug_print_table(const char *info, TABLE *table)
(f->flags & BINARY_FLAG) ? ",binary" : "",
f->real_type(),
f->pack_length(),
- f->ptr, f->ptr - table->record[0],
+ (long) f->ptr, (int) (f->ptr - table->record[0]),
f->null_bit,
- f->null_ptr, (byte*) f->null_ptr - table->record[0]));
+ (long) f->null_ptr,
+ (int) ((byte*) f->null_ptr - table->record[0])));
if (f->type() == MYSQL_TYPE_BIT)
{
Field_bit *g= (Field_bit*) f;
DBUG_PRINT("MYSQL_TYPE_BIT",("field_length: %d bit_ptr: 0x%lx[+%d] "
- "bit_ofs: %u bit_len: %u",
- g->field_length, g->bit_ptr,
- (byte*) g->bit_ptr-table->record[0],
+ "bit_ofs: %d bit_len: %u",
+ g->field_length, (long) g->bit_ptr,
+ (int) ((byte*) g->bit_ptr -
+ table->record[0]),
g->bit_ofs, g->bit_len));
}
}
@@ -605,11 +607,11 @@ static int ndbcluster_binlog_end(THD *thd)
{
DBUG_PRINT("share",
("[%d] 0x%lx key: %s key_length: %d",
- i, share, share->key, share->key_length));
+ i, (long) share, share->key, share->key_length));
DBUG_PRINT("share",
- ("db.tablename: %s.%s use_count: %d commit_count: %d",
+ ("db.tablename: %s.%s use_count: %d commit_count: %lu",
share->db, share->table_name,
- share->use_count, share->commit_count));
+ share->use_count, (long) share->commit_count));
}
}
pthread_mutex_unlock(&ndbcluster_mutex);
@@ -685,8 +687,8 @@ static NDB_SHARE *ndbcluster_check_apply_status_share()
void *share= hash_search(&ndbcluster_open_tables,
NDB_APPLY_TABLE_FILE,
sizeof(NDB_APPLY_TABLE_FILE) - 1);
- DBUG_PRINT("info",("ndbcluster_check_apply_status_share %s %p",
- NDB_APPLY_TABLE_FILE, share));
+ DBUG_PRINT("info",("ndbcluster_check_apply_status_share %s 0x%lx",
+ NDB_APPLY_TABLE_FILE, (long) share));
pthread_mutex_unlock(&ndbcluster_mutex);
return (NDB_SHARE*) share;
}
@@ -703,8 +705,8 @@ static NDB_SHARE *ndbcluster_check_schema_share()
void *share= hash_search(&ndbcluster_open_tables,
NDB_SCHEMA_TABLE_FILE,
sizeof(NDB_SCHEMA_TABLE_FILE) - 1);
- DBUG_PRINT("info",("ndbcluster_check_schema_share %s %p",
- NDB_SCHEMA_TABLE_FILE, share));
+ DBUG_PRINT("info",("ndbcluster_check_schema_share %s 0x%lx",
+ NDB_SCHEMA_TABLE_FILE, (long) share));
pthread_mutex_unlock(&ndbcluster_mutex);
return (NDB_SHARE*) share;
}
@@ -2721,10 +2723,9 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
if (share->flags & NSF_BLOB_FLAG)
op->mergeEvents(TRUE); // currently not inherited from event
- DBUG_PRINT("info", ("share->ndb_value[0]: 0x%x",
- share->ndb_value[0]));
- DBUG_PRINT("info", ("share->ndb_value[1]: 0x%x",
- share->ndb_value[1]));
+ DBUG_PRINT("info", ("share->ndb_value[0]: 0x%lx share->ndb_value[1]: 0x%lx",
+ (long) share->ndb_value[0],
+ (long) share->ndb_value[1]));
int n_columns= ndbtab->getNoOfColumns();
int n_fields= table ? table->s->fields : 0; // XXX ???
for (int j= 0; j < n_columns; j++)
@@ -2778,12 +2779,14 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
}
share->ndb_value[0][j].ptr= attr0.ptr;
share->ndb_value[1][j].ptr= attr1.ptr;
- DBUG_PRINT("info", ("&share->ndb_value[0][%d]: 0x%x "
- "share->ndb_value[0][%d]: 0x%x",
- j, &share->ndb_value[0][j], j, attr0.ptr));
- DBUG_PRINT("info", ("&share->ndb_value[1][%d]: 0x%x "
- "share->ndb_value[1][%d]: 0x%x",
- j, &share->ndb_value[0][j], j, attr1.ptr));
+ DBUG_PRINT("info", ("&share->ndb_value[0][%d]: 0x%lx "
+ "share->ndb_value[0][%d]: 0x%lx",
+ j, (long) &share->ndb_value[0][j],
+ j, (long) attr0.ptr));
+ DBUG_PRINT("info", ("&share->ndb_value[1][%d]: 0x%lx "
+ "share->ndb_value[1][%d]: 0x%lx",
+ j, (long) &share->ndb_value[0][j],
+ j, (long) attr1.ptr));
}
op->setCustomData((void *) share); // set before execute
share->op= op; // assign op in NDB_SHARE
@@ -2826,8 +2829,8 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
(void) pthread_cond_signal(&injector_cond);
}
- DBUG_PRINT("info",("%s share->op: 0x%lx, share->use_count: %u",
- share->key, share->op, share->use_count));
+ DBUG_PRINT("info",("%s share->op: 0x%lx share->use_count: %u",
+ share->key, (long) share->op, share->use_count));
if (ndb_extra_logging)
sql_print_information("NDB Binlog: logging %s", share->key);
@@ -3012,10 +3015,11 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb,
free_share(&apply_status_share);
apply_status_share= 0;
}
- DBUG_PRINT("info", ("CLUSTER FAILURE EVENT: "
- "%s received share: 0x%lx op: %lx share op: %lx "
- "op_old: %lx",
- share->key, share, pOp, share->op, share->op_old));
+ DBUG_PRINT("error", ("CLUSTER FAILURE EVENT: "
+ "%s received share: 0x%lx op: 0x%lx share op: 0x%lx "
+ "op_old: 0x%lx",
+ share->key, (long) share, (long) pOp,
+ (long) share->op, (long) share->op_old));
break;
case NDBEVENT::TE_DROP:
if (apply_status_share == share)
@@ -3033,10 +3037,11 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb,
// fall through
case NDBEVENT::TE_ALTER:
row.n_schemaops++;
- DBUG_PRINT("info", ("TABLE %s EVENT: %s received share: 0x%lx op: %lx "
- "share op: %lx op_old: %lx",
- type == NDBEVENT::TE_DROP ? "DROP" : "ALTER",
- share->key, share, pOp, share->op, share->op_old));
+ DBUG_PRINT("info", ("TABLE %s EVENT: %s received share: 0x%lx op: 0x%lx "
+ "share op: 0x%lx op_old: 0x%lx",
+ type == NDBEVENT::TE_DROP ? "DROP" : "ALTER",
+ share->key, (long) share, (long) pOp,
+ (long) share->op, (long) share->op_old));
break;
case NDBEVENT::TE_NODE_FAILURE:
/* fall through */
@@ -3436,7 +3441,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
global_system_variables.binlog_format == BINLOG_FORMAT_MIXED)
{
ndb_binlog_running= TRUE;
- thd->current_stmt_binlog_row_based= TRUE; // If in mixed mode
}
else
{
@@ -3514,7 +3518,8 @@ restart:
}
}
// now check that we have epochs consistant with what we had before the restart
- DBUG_PRINT("info", ("schema_res: %d schema_gci: %d", schema_res, schema_gci));
+ DBUG_PRINT("info", ("schema_res: %d schema_gci: %lu", schema_res,
+ (long) schema_gci));
{
i_ndb->flushIncompleteEvents(schema_gci);
s_ndb->flushIncompleteEvents(schema_gci);
@@ -3558,9 +3563,11 @@ restart:
if (do_ndbcluster_binlog_close_connection)
{
DBUG_PRINT("info", ("do_ndbcluster_binlog_close_connection: %d, "
- "ndb_latest_handled_binlog_epoch: %llu, "
- "*p_latest_trans_gci: %llu", do_ndbcluster_binlog_close_connection,
- ndb_latest_handled_binlog_epoch, *p_latest_trans_gci));
+ "ndb_latest_handled_binlog_epoch: %lu, "
+ "*p_latest_trans_gci: %lu",
+ do_ndbcluster_binlog_close_connection,
+ (ulong) ndb_latest_handled_binlog_epoch,
+ (ulong) *p_latest_trans_gci));
}
#endif
#ifdef RUN_NDB_BINLOG_TIMER
@@ -3648,9 +3655,10 @@ restart:
do_ndbcluster_binlog_close_connection= BCCC_restart;
if (ndb_latest_received_binlog_epoch < *p_latest_trans_gci && ndb_binlog_running)
{
- sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog "
- "as latest received epoch is %lld",
- *p_latest_trans_gci, ndb_latest_received_binlog_epoch);
+ sql_print_error("NDB Binlog: latest transaction in epoch %lu not in binlog "
+ "as latest received epoch is %lu",
+ (ulong) *p_latest_trans_gci,
+ (ulong) ndb_latest_received_binlog_epoch);
}
}
}
@@ -3698,8 +3706,8 @@ restart:
!= NULL)
{
NDB_SHARE *share= (NDB_SHARE*)gci_op->getCustomData();
- DBUG_PRINT("info", ("per gci_op: %p share: %p event_types: 0x%x",
- gci_op, share, event_types));
+ DBUG_PRINT("info", ("per gci_op: 0x%lx share: 0x%lx event_types: 0x%x",
+ (long) gci_op, (long) share, event_types));
// workaround for interface returning TE_STOP events
// which are normally filtered out below in the nextEvent loop
if ((event_types & ~NdbDictionary::Event::TE_STOP) == 0)
@@ -3785,11 +3793,13 @@ restart:
{
NDB_SHARE *share= (NDB_SHARE*) pOp->getCustomData();
DBUG_PRINT("info",
- ("EVENT TYPE: %d GCI: %lld last applied: %lld "
- "share: 0x%lx (%s.%s)", pOp->getEventType(), gci,
- ndb_latest_applied_binlog_epoch, share,
- share ? share->db : "share == NULL",
- share ? share->table_name : ""));
+ ("EVENT TYPE: %d GCI: %ld last applied: %ld "
+ "share: 0x%lx (%s.%s)", pOp->getEventType(),
+ (long) gci,
+ (long) ndb_latest_applied_binlog_epoch,
+ (long) share,
+ share ? share->db : "'NULL'",
+ share ? share->table_name : "'NULL'"));
DBUG_ASSERT(share != 0);
}
// assert that there is consistancy between gci op list
@@ -3834,9 +3844,10 @@ restart:
do_ndbcluster_binlog_close_connection= BCCC_restart;
if (ndb_latest_received_binlog_epoch < *p_latest_trans_gci && ndb_binlog_running)
{
- sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog "
- "as latest received epoch is %lld",
- *p_latest_trans_gci, ndb_latest_received_binlog_epoch);
+ sql_print_error("NDB Binlog: latest transaction in epoch %lu not in binlog "
+ "as latest received epoch is %lu",
+ (ulong) *p_latest_trans_gci,
+ (ulong) ndb_latest_received_binlog_epoch);
}
}
}
@@ -3868,7 +3879,7 @@ restart:
row.master_log_file= start.file_name();
row.master_log_pos= start.file_pos();
- DBUG_PRINT("info", ("COMMIT gci: %lld", gci));
+ DBUG_PRINT("info", ("COMMIT gci: %lu", (ulong) gci));
if (ndb_update_binlog_index)
ndb_add_binlog_index(thd, &row);
ndb_latest_applied_binlog_epoch= gci;
diff --git a/sql/ha_ndbcluster_tables.h b/sql/ha_ndbcluster_tables.h
index 12124cd8820..9d7fda33102 100644
--- a/sql/ha_ndbcluster_tables.h
+++ b/sql/ha_ndbcluster_tables.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define NDB_REP_DB "cluster"
+#define NDB_REP_DB "mysql"
#define NDB_REP_TABLE "binlog_index"
#define NDB_APPLY_TABLE "apply_status"
#define NDB_SCHEMA_TABLE "schema"
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 3edd3923779..7cd33dd5726 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -2027,7 +2027,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root)
if (!(m_file[i]= get_new_handler(table_share, mem_root,
m_engine_array[i])))
DBUG_RETURN(TRUE);
- DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]));
+ DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]->db_type));
}
/* For the moment we only support partition over the same table engine */
if (m_engine_array[0] == myisam_hton)
@@ -2427,7 +2427,7 @@ repeat:
do
{
DBUG_PRINT("info", ("external_lock(thd, %d) iteration %d",
- lock_type, (file - m_file)));
+ lock_type, (int) (file - m_file)));
if ((error= (*file)->external_lock(thd, lock_type)))
{
if (F_UNLCK != lock_type)
@@ -2508,7 +2508,7 @@ THR_LOCK_DATA **ha_partition::store_lock(THD *thd,
file= m_file;
do
{
- DBUG_PRINT("info", ("store lock %d iteration", (file - m_file)));
+ DBUG_PRINT("info", ("store lock %d iteration", (int) (file - m_file)));
to= (*file)->store_lock(thd, to, lock_type);
} while (*(++file));
DBUG_RETURN(to);
@@ -2939,8 +2939,8 @@ int ha_partition::rnd_init(bool scan)
include_partition_fields_in_used_fields();
/* Now we see what the index of our first important partition is */
- DBUG_PRINT("info", ("m_part_info->used_partitions 0x%x",
- m_part_info->used_partitions.bitmap));
+ DBUG_PRINT("info", ("m_part_info->used_partitions: 0x%lx",
+ (long) m_part_info->used_partitions.bitmap));
part_id= bitmap_get_first_set(&(m_part_info->used_partitions));
DBUG_PRINT("info", ("m_part_spec.start_part %d", part_id));
diff --git a/sql/handler.cc b/sql/handler.cc
index 451f974a066..f874100e634 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1513,7 +1513,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
DBUG_ENTER("handler::ha_open");
DBUG_PRINT("enter",
("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
- name, table_share->db_type, table_arg->db_stat, mode,
+ name, ht->db_type, table_arg->db_stat, mode,
test_if_locked));
table= table_arg;
@@ -1654,7 +1654,7 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
*/
DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
"auto_increment_offset: %lu",
- nr, variables->auto_increment_offset));
+ (ulong) nr, variables->auto_increment_offset));
return nr;
}
if (variables->auto_increment_increment == 1)
@@ -1927,8 +1927,8 @@ int handler::update_auto_increment()
void handler::column_bitmaps_signal()
{
DBUG_ENTER("column_bitmaps_signal");
- DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", table->read_set,
- table->write_set));
+ DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", (long) table->read_set,
+ (long) table->write_set));
DBUG_VOID_RETURN;
}
@@ -3460,38 +3460,15 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
declared static, but it works by putting it into an anonymous
namespace. */
namespace {
- struct st_table_data {
- char const *db;
- char const *name;
- };
-
- static int table_name_compare(void const *a, void const *b)
- {
- st_table_data const *x = (st_table_data const*) a;
- st_table_data const *y = (st_table_data const*) b;
-
- /* Doing lexical compare in order (db,name) */
- int const res= strcmp(x->db, y->db);
- return res != 0 ? res : strcmp(x->name, y->name);
- }
-
bool check_table_binlog_row_based(THD *thd, TABLE *table)
{
- static st_table_data const ignore[] = {
- { "mysql", "event" },
- { "mysql", "general_log" },
- { "mysql", "slow_log" }
- };
-
- my_size_t const ignore_size = sizeof(ignore)/sizeof(*ignore);
- st_table_data const item = { table->s->db.str, table->s->table_name.str };
-
if (table->s->cached_row_logging_check == -1)
- table->s->cached_row_logging_check=
- (table->s->tmp_table == NO_TMP_TABLE) &&
- binlog_filter->db_ok(table->s->db.str) &&
- bsearch(&item, ignore, ignore_size,
- sizeof(st_table_data), table_name_compare) == NULL;
+ {
+ int const check(table->s->tmp_table == NO_TMP_TABLE &&
+ binlog_filter->db_ok(table->s->db.str) &&
+ strcmp("mysql", table->s->db.str) != 0);
+ table->s->cached_row_logging_check= check;
+ }
DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
table->s->cached_row_logging_check == 1);
@@ -3530,8 +3507,10 @@ namespace
int write_locked_table_maps(THD *thd)
{
DBUG_ENTER("write_locked_table_maps");
- DBUG_PRINT("enter", ("thd=%p, thd->lock=%p, thd->locked_tables=%p, thd->extra_lock",
- thd, thd->lock, thd->locked_tables, thd->extra_lock));
+ DBUG_PRINT("enter", ("thd: 0x%lx thd->lock: 0x%lx thd->locked_tables: 0x%lx "
+ "thd->extra_lock: 0x%lx",
+ (long) thd, (long) thd->lock,
+ (long) thd->locked_tables, (long) thd->extra_lock));
if (thd->get_binlog_table_maps() == 0)
{
@@ -3551,7 +3530,7 @@ namespace
++table_ptr)
{
TABLE *const table= *table_ptr;
- DBUG_PRINT("info", ("Checking table %s", table->s->table_name));
+ DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
if (table->current_lock == F_WRLCK &&
check_table_binlog_row_based(thd, table))
{
diff --git a/sql/item.cc b/sql/item.cc
index f8a8b4a6272..6ab9a90ffe3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1655,7 +1655,7 @@ void Item_field::set_field(Field *field_par)
db_name= field_par->table->s->db.str;
alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
- collation.set(field_par->charset(), DERIVATION_IMPLICIT);
+ collation.set(field_par->charset(), field_par->derivation());
fixed= 1;
}
diff --git a/sql/item.h b/sql/item.h
index 8799fa07eb7..2c26e1c4a07 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -27,19 +27,7 @@ class Item_field;
/*
"Declared Type Collation"
A combination of collation and its derivation.
-*/
-enum Derivation
-{
- DERIVATION_IGNORABLE= 5,
- DERIVATION_COERCIBLE= 4,
- DERIVATION_SYSCONST= 3,
- DERIVATION_IMPLICIT= 2,
- DERIVATION_NONE= 1,
- DERIVATION_EXPLICIT= 0
-};
-
-/*
Flags for collation aggregation modes:
MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 79d37c50030..cfd367944e6 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2229,7 +2229,7 @@ cmp_item* cmp_item_row::make_same()
cmp_item_row::~cmp_item_row()
{
DBUG_ENTER("~cmp_item_row");
- DBUG_PRINT("enter",("this: 0x%lx", this));
+ DBUG_PRINT("enter",("this: 0x%lx", (long) this));
if (comparators)
{
for (uint i= 0; i < n; i++)
@@ -3060,7 +3060,7 @@ longlong Item_is_not_null_test::val_int()
if (!used_tables_cache)
{
owner->was_null|= (!cached_value);
- DBUG_PRINT("info", ("cached :%d", cached_value));
+ DBUG_PRINT("info", ("cached: %ld", (long) cached_value));
DBUG_RETURN(cached_value);
}
if (args[0]->is_null())
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d1c346ac43e..76bec5c4967 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -5051,7 +5051,7 @@ Item_func_sp::result_type() const
{
Field *field;
DBUG_ENTER("Item_func_sp::result_type");
- DBUG_PRINT("info", ("m_sp = %p", m_sp));
+ DBUG_PRINT("info", ("m_sp: 0x%lx", (long) m_sp));
if (result_field)
DBUG_RETURN(result_field->result_type());
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5b602314a55..32b283fca57 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -992,8 +992,8 @@ String *Item_func_insert::val_str(String *str)
if (length > res->length() - start)
length= res->length() - start;
- if (res->length() - length + res2->length() >
- current_thd->variables.max_allowed_packet)
+ if ((ulonglong) (res->length() - length + res2->length()) >
+ (ulonglong) current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
@@ -2485,7 +2485,7 @@ String *Item_func_lpad::val_str(String *str)
pad_char_length= pad->numchars();
byte_count= count * collation.collation->mbmaxlen;
- if (byte_count > current_thd->variables.max_allowed_packet)
+ if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4e6c67cba60..fcf34240189 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -54,7 +54,7 @@ void Item_subselect::init(st_select_lex *select_lex,
{
DBUG_ENTER("Item_subselect::init");
- DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
+ DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex));
unit= select_lex->master_unit();
if (unit->item)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 0d18cf1d424..bb629129667 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2933,13 +2933,14 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
*/
Field *field= (*field_item)->get_tmp_table_field();
/*
- If field_item is a const item then either get_tp_table_field returns 0
+ If field_item is a const item then either get_tmp_table_field returns 0
or it is an item over a const table.
*/
if (field && !(*field_item)->const_item())
{
int res;
- uint offset= field->offset() - table->s->null_bytes;
+ uint offset= (field->offset(field->table->record[0]) -
+ table->s->null_bytes);
if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
return res;
}
@@ -2977,7 +2978,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
if (field && !item->const_item())
{
int res;
- uint offset= field->offset() - table->s->null_bytes;
+ uint offset= (field->offset(field->table->record[0]) -
+ table->s->null_bytes);
if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
return (*order_item)->asc ? res : -res;
}
@@ -3023,6 +3025,7 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
String tmp2;
String *result= &item->result;
Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
+ uint old_length= result->length();
if (item->no_appended)
item->no_appended= FALSE;
@@ -3044,7 +3047,8 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
because it contains both order and arg list fields.
*/
Field *field= (*arg)->get_tmp_table_field();
- uint offset= field->offset() - table->s->null_bytes;
+ uint offset= (field->offset(field->table->record[0]) -
+ table->s->null_bytes);
DBUG_ASSERT(offset < table->s->reclength);
res= field->val_str(&tmp, (char *) key + offset);
}
@@ -3057,8 +3061,22 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
/* stop if length of result more than max_length */
if (result->length() > item->max_length)
{
+ int well_formed_error;
+ CHARSET_INFO *cs= item->collation.collation;
+ const char *ptr= result->ptr();
+ uint add_length;
+ /*
+ It's ok to use item->result.length() as the fourth argument
+ as this is never used to limit the length of the data.
+ Cut is done with the third argument.
+ */
+ add_length= cs->cset->well_formed_len(cs,
+ ptr + old_length,
+ ptr + item->max_length,
+ result->length(),
+ &well_formed_error);
+ result->length(old_length + add_length);
item->count_cut_values++;
- result->length(item->max_length);
item->warning_for_row= TRUE;
return 1;
}
@@ -3248,8 +3266,7 @@ bool Item_func_group_concat::add()
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
instead of doing tree traverse later.
*/
- if (result.length() <= max_length &&
- !warning_for_row &&
+ if (!warning_for_row &&
(!tree || (el->count == 1 && distinct && !arg_count_order)))
dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this);
@@ -3318,7 +3335,8 @@ bool Item_func_group_concat::setup(THD *thd)
DBUG_RETURN(TRUE);
/* We'll convert all blobs to varchar fields in the temporary table */
- tmp_table_param->convert_blob_length= max_length;
+ tmp_table_param->convert_blob_length= max_length *
+ collation.collation->mbmaxlen;
/* Push all not constant fields to the list and create a temp table */
always_null= 0;
for (uint i= 0; i < arg_count_field; i++)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 3d49305cfd3..d14feb2ba68 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1368,11 +1368,9 @@ bool get_interval_value(Item *args,interval_type int_type,
interval->second= array[0];
interval->second_part= array[1];
break;
- /* purecov: begin deadcode */
- case INTERVAL_LAST:
- DBUG_ASSERT(0);
- break;
- /* purecov: end */
+ case INTERVAL_LAST: /* purecov: begin deadcode */
+ DBUG_ASSERT(0);
+ break; /* purecov: end */
}
return 0;
}
@@ -2199,7 +2197,7 @@ void Item_extract::fix_length_and_dec()
case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
- case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
+ case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
}
}
@@ -2269,8 +2267,7 @@ longlong Item_extract::val_int()
ltime.second_part)*neg;
case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
ltime.second_part)*neg;
- case INTERVAL_LAST: DBUG_ASSERT(0); return(0); /* purecov: deadcode */
- /* purecov: end */
+ case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
}
return 0; // Impossible
}
@@ -2385,7 +2382,8 @@ String *Item_char_typecast::val_str(String *str)
{ // Safe even if const arg
char char_type[40];
my_snprintf(char_type, sizeof(char_type), "%s(%lu)",
- cast_cs == &my_charset_bin ? "BINARY" : "CHAR", (ulong) length);
+ cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
+ (ulong) length);
if (!res->alloced_length())
{ // Don't change const str
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 44a2b690bac..21239a13735 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -532,7 +532,7 @@ public:
longlong val_int()
{
Item_func *comp= (Item_func*)args[1];
- Item_string *fake= (Item_string*)(comp->arguments()[1]);
+ Item_string *fake= (Item_string*)(comp->arguments()[0]);
String *res= args[0]->val_nodeset(&tmp_nodeset);
MY_XPATH_FLT *fltbeg= (MY_XPATH_FLT*) res->ptr();
MY_XPATH_FLT *fltend= (MY_XPATH_FLT*) (res->ptr() + res->length());
@@ -884,7 +884,7 @@ static Item *eq_func(int oper, Item *a, Item *b)
Create a comparator function for scalar arguments,
for the given arguments and reverse operation, e.g.
- A >= B is converted into A < B
+ A > B is converted into B < A
RETURN
The newly created item.
@@ -895,10 +895,10 @@ static Item *eq_func_reverse(int oper, Item *a, Item *b)
{
case '=': return new Item_func_eq(a, b);
case '!': return new Item_func_ne(a, b);
- case MY_XPATH_LEX_GE: return new Item_func_lt(a, b);
- case MY_XPATH_LEX_LE: return new Item_func_gt(a, b);
- case MY_XPATH_LEX_GREATER: return new Item_func_le(a, b);
- case MY_XPATH_LEX_LESS: return new Item_func_ge(a, b);
+ case MY_XPATH_LEX_GE: return new Item_func_le(a, b);
+ case MY_XPATH_LEX_LE: return new Item_func_ge(a, b);
+ case MY_XPATH_LEX_GREATER: return new Item_func_lt(a, b);
+ case MY_XPATH_LEX_LESS: return new Item_func_gt(a, b);
}
return 0;
}
@@ -951,13 +951,13 @@ static Item *create_comparator(MY_XPATH *xpath,
{
nodeset= (Item_nodeset_func*) a;
scalar= b;
- comp= eq_func(oper, scalar, fake);
+ comp= eq_func(oper, fake, scalar);
}
else
{
nodeset= (Item_nodeset_func*) b;
scalar= a;
- comp= eq_func_reverse(oper, scalar, fake);
+ comp= eq_func_reverse(oper, fake, scalar);
}
return new Item_nodeset_to_const_comparator(nodeset, comp, xpath->pxml);
}
diff --git a/sql/key.cc b/sql/key.cc
index be21bf11c3c..dceeab1c011 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -19,37 +19,54 @@
#include "mysql_priv.h"
- /*
- ** Search after with key field is. If no key starts with field test
- ** if field is part of some key.
- **
- ** returns number of key. keylength is set to length of key before
- ** (not including) field
- ** Used when calculating key for NEXT_NUMBER
- */
-
-int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length)
+/*
+ Search after a key that starts with 'field'
+
+ SYNOPSIS
+ find_ref_key()
+ key First key to check
+ key_count How many keys to check
+ record Start of record
+ field Field to search after
+ key_length On partial match, contains length of fields before
+ field
+
+ NOTES
+ Used when calculating key for NEXT_NUMBER
+
+ IMPLEMENTATION
+ If no key starts with field test if field is part of some key. If we find
+ one, then return first key and set key_length to the number of bytes
+ preceding 'field'.
+
+ RETURN
+ -1 field is not part of the key
+ # Key part for key matching key.
+ key_length is set to length of key before (not including) field
+*/
+
+int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
+ uint *key_length)
{
reg2 int i;
reg3 KEY *key_info;
uint fieldpos;
- fieldpos= field->offset();
-
- /* Test if some key starts as fieldpos */
+ fieldpos= field->offset(record);
+ /* Test if some key starts as fieldpos */
for (i= 0, key_info= key ;
i < (int) key_count ;
i++, key_info++)
{
if (key_info->key_part[0].offset == fieldpos)
- { /* Found key. Calc keylength */
+ { /* Found key. Calc keylength */
*key_length=0;
- return(i); /* Use this key */
+ return(i); /* Use this key */
}
}
- /* Test if some key contains fieldpos */
+ /* Test if some key contains fieldpos */
for (i= 0, key_info= key;
i < (int) key_count ;
i++, key_info++)
@@ -62,7 +79,7 @@ int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length)
j++, key_part++)
{
if (key_part->offset == fieldpos)
- return(i); /* Use this key */
+ return(i); /* Use this key */
*key_length+=key_part->store_length;
}
}
diff --git a/sql/log.cc b/sql/log.cc
index 83e190a5c01..b12eca9bb07 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -424,6 +424,18 @@ bool Log_to_csv_event_handler::
{
TABLE *table= general_log.table;
+ /*
+ "INSERT INTO general_log" can generate warning sometimes.
+ Let's reset warnings from previous queries,
+ otherwise warning list can grow too much,
+ so thd->query gets spoiled as some point in time,
+ and mysql_parse() receives a broken query.
+ QQ: this problem needs to be studied in more details.
+ Probably it's better to suppress warnings in logging INSERTs at all.
+ Comment this line and run "cast.test" to see what's happening:
+ */
+ mysql_reset_errors(table->in_use, 1);
+
/* below should never happen */
if (unlikely(!logger.is_log_tables_initialized))
return FALSE;
@@ -1332,7 +1344,7 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos)
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
DBUG_ASSERT(mysql_bin_log.is_open());
*pos= trx_data->position();
- DBUG_PRINT("return", ("*pos=%u", *pos));
+ DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
DBUG_VOID_RETURN;
}
@@ -1356,7 +1368,7 @@ static void
binlog_trans_log_truncate(THD *thd, my_off_t pos)
{
DBUG_ENTER("binlog_trans_log_truncate");
- DBUG_PRINT("enter", ("pos=%u", pos));
+ DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
DBUG_ASSERT(thd->ha_data[binlog_hton->slot] != NULL);
/* Only true if binlog_trans_log_savepos() wasn't called before */
@@ -1432,8 +1444,8 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
DBUG_ENTER("binlog_end_trans");
int error=0;
IO_CACHE *trans_log= &trx_data->trans_log;
- DBUG_PRINT("enter", ("transaction: %s, end_ev=%p",
- all ? "all" : "stmt", end_ev));
+ DBUG_PRINT("enter", ("transaction: %s end_ev: 0x%lx",
+ all ? "all" : "stmt", (long) end_ev));
DBUG_PRINT("info", ("thd->options={ %s%s}",
FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
FLAGSTR(thd->options, OPTION_BEGIN)));
@@ -3405,12 +3417,13 @@ int THD::binlog_setup_trx_data()
void
THD::binlog_start_trans_and_stmt()
{
- DBUG_ENTER("binlog_start_trans_and_stmt");
binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
- DBUG_PRINT("enter", ("trx_data=0x%lu", trx_data));
- if (trx_data)
- DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%u",
- trx_data->before_stmt_pos));
+ DBUG_ENTER("binlog_start_trans_and_stmt");
+ DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu",
+ (long) trx_data,
+ (trx_data ? (ulong) trx_data->before_stmt_pos :
+ (ulong) 0)));
+
if (trx_data == NULL ||
trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
{
@@ -3441,8 +3454,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
{
int error;
DBUG_ENTER("THD::binlog_write_table_map");
- DBUG_PRINT("enter", ("table: %0xlx (%s: #%u)",
- (long) table, table->s->table_name,
+ DBUG_PRINT("enter", ("table: 0x%lx (%s: #%lu)",
+ (long) table, table->s->table_name.str,
table->s->table_map_id));
/* Pre-conditions */
@@ -3505,7 +3518,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
{
DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
DBUG_ASSERT(mysql_bin_log.is_open());
- DBUG_PRINT("enter", ("event=%p", event));
+ DBUG_PRINT("enter", ("event: 0x%lx", (long) event));
int error= 0;
@@ -3514,7 +3527,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
DBUG_ASSERT(trx_data);
- DBUG_PRINT("info", ("trx_data->pending()=%p", trx_data->pending()));
+ DBUG_PRINT("info", ("trx_data->pending(): 0x%lx", (long) trx_data->pending()));
if (Rows_log_event* pending= trx_data->pending())
{
@@ -3669,9 +3682,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
my_off_t trans_log_pos= my_b_tell(trans_log);
if (event_info->get_cache_stmt() || trans_log_pos != 0)
{
- DBUG_PRINT("info", ("Using trans_log: cache=%d, trans_log_pos=%u",
+ DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
event_info->get_cache_stmt(),
- trans_log_pos));
+ (ulong) trans_log_pos));
if (trans_log_pos == 0)
thd->binlog_start_trans_and_stmt();
file= trans_log;
@@ -3713,15 +3726,17 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
}
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
{
- DBUG_PRINT("info",("number of auto_inc intervals: %lu",
- thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements()));
+ DBUG_PRINT("info",("number of auto_inc intervals: %u",
+ thd->auto_inc_intervals_in_cur_stmt_for_binlog.
+ nb_elements()));
/*
If the auto_increment was second in a table's index (possible with
MyISAM or BDB) (table->next_number_key_offset != 0), such event is
in fact not necessary. We could avoid logging it.
*/
- Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,
- thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum());
+ Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
+ thd->auto_inc_intervals_in_cur_stmt_for_binlog.
+ minimum());
if (e.write(file))
goto err;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d99fb9da8f8..112f4aee135 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -140,6 +140,21 @@ static void pretty_print_str(IO_CACHE* cache, char* str, int len)
}
#endif /* MYSQL_CLIENT */
+#ifdef HAVE_purify
+static void
+valgrind_check_mem(void *ptr, size_t len)
+{
+ static volatile uchar dummy;
+ for (volatile uchar *p= (uchar*) ptr ; p != (uchar*) ptr + len ; ++p)
+ {
+ int const c = *p;
+ if (c < 128)
+ dummy= c + 1;
+ else
+ dummy = c - 1;
+ }
+}
+#endif
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
@@ -831,7 +846,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file,
LOG_EVENT_MINIMAL_HEADER_LEN);
LOCK_MUTEX;
- DBUG_PRINT("info", ("my_b_tell=%lu", my_b_tell(file)));
+ DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file)));
if (my_b_read(file, (byte *) head, header_size))
{
DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \
@@ -1398,6 +1413,7 @@ bool Query_log_event::write(IO_CACHE* file)
/* Store length of status variables */
status_vars_len= (uint) (start-start_of_status);
+ DBUG_ASSERT(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
/*
@@ -1483,7 +1499,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
}
else
time_zone_len= 0;
- DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
+ DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu",
+ (ulong) flags2, sql_mode));
}
#endif /* MYSQL_CLIENT */
@@ -1531,7 +1548,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
common_header_len= description_event->common_header_len;
post_header_len= description_event->post_header_len[event_type-1];
- DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d",
+ DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
event_len, common_header_len, post_header_len));
/*
@@ -1579,7 +1596,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
case Q_FLAGS2_CODE:
flags2_inited= 1;
flags2= uint4korr(pos);
- DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", flags2));
+ DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", (ulong) flags2));
pos+= 4;
break;
case Q_SQL_MODE_CODE:
@@ -3354,8 +3371,8 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
#ifndef DBUG_OFF
char buff[22];
DBUG_ENTER("Rotate_log_event::Rotate_log_event(...,flags)");
- DBUG_PRINT("enter",("new_log_ident %s pos %s flags %lu", new_log_ident_arg,
- llstr(pos_arg, buff), flags));
+ DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg,
+ llstr(pos_arg, buff), (ulong) flags));
#endif
if (flags & DUP_NAME)
new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
@@ -4136,7 +4153,7 @@ Slave_log_event::Slave_log_event(THD* thd_arg,
memcpy(master_log, rli->group_master_log_name, master_log_len + 1);
master_port = mi->port;
master_pos = rli->group_master_log_pos;
- DBUG_PRINT("info", ("master_log: %s pos: %d", master_log,
+ DBUG_PRINT("info", ("master_log: %s pos: %lu", master_log,
(ulong) master_pos));
}
else
@@ -5328,8 +5345,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
uint8 const common_header_len= description_event->common_header_len;
uint8 const post_header_len= description_event->post_header_len[event_type-1];
- DBUG_PRINT("enter",("event_len=%ld, common_header_len=%d, "
- "post_header_len=%d",
+ DBUG_PRINT("enter",("event_len: %u common_header_len: %d "
+ "post_header_len: %d",
event_len, common_header_len,
post_header_len));
@@ -5359,7 +5376,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
const byte* const ptr_rows_data= var_start + byte_count + 1;
my_size_t const data_size= event_len - (ptr_rows_data - (const byte *) buf);
- DBUG_PRINT("info",("m_table_id=%lu, m_flags=%d, m_width=%u, data_size=%lu",
+ DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu",
m_table_id, m_flags, m_width, data_size));
m_rows_buf= (byte*)my_malloc(data_size, MYF(MY_WME));
@@ -5400,8 +5417,14 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
*/
DBUG_ENTER("Rows_log_event::do_add_row_data");
DBUG_PRINT("enter", ("row_data: 0x%lx length: %lu", (ulong) row_data,
- length));
+ (ulong) length));
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
DBUG_DUMP("row_data", (const char*)row_data, min(length, 32));
+#endif
DBUG_ASSERT(m_rows_buf <= m_rows_cur);
DBUG_ASSERT(!m_rows_buf || m_rows_end && m_rows_buf < m_rows_end);
@@ -5445,14 +5468,13 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
/*
- Unpack a row into a record.
+ Unpack a row into table->record[0].
SYNOPSIS
unpack_row()
rli Relay log info
table Table to unpack into
colcnt Number of columns to read from record
- record Record where the data should be unpacked
row Packed row data
cols Pointer to columns data to fill in
row_end Pointer to variable that will hold the value of the
@@ -5465,6 +5487,11 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
DESCRIPTION
+ The function will always unpack into the table->record[0]
+ record. This is because there are too many dependencies on
+ where the various member functions of Field and subclasses
+ expect to write.
+
The row is assumed to only consist of the fields for which the
bitset represented by 'arr' and 'bits'; the other parts of the
record are left alone.
@@ -5483,13 +5510,15 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
*/
static int
unpack_row(RELAY_LOG_INFO *rli,
- TABLE *table, uint const colcnt, byte *record,
+ TABLE *table, uint const colcnt,
char const *row, MY_BITMAP const *cols,
char const **row_end, ulong *master_reclength,
MY_BITMAP* const rw_set, Log_event_type const event_type)
{
+ byte *const record= table->record[0];
+ DBUG_ENTER("unpack_row");
DBUG_ASSERT(record && row);
- my_ptrdiff_t const offset= record - (byte*) table->record[0];
+ DBUG_PRINT("enter", ("row: 0x%lx table->record[0]: 0x%lx", (long) row, (long) record));
my_size_t master_null_bytes= table->s->null_bytes;
if (colcnt != table->s->fields)
@@ -5529,9 +5558,13 @@ unpack_row(RELAY_LOG_INFO *rli,
if (bitmap_is_set(cols, field_ptr - begin_ptr))
{
- f->move_field_offset(offset);
+ DBUG_ASSERT(table->record[0] <= f->ptr);
+ DBUG_ASSERT(f->ptr < (table->record[0] + table->s->reclength +
+ (f->pack_length_in_rec() == 0)));
+
+ DBUG_PRINT("info", ("unpacking column '%s' to 0x%lx", f->field_name,
+ (long) f->ptr));
ptr= f->unpack(f->ptr, ptr);
- f->move_field_offset(-offset);
/* Field...::unpack() cannot return 0 */
DBUG_ASSERT(ptr != NULL);
}
@@ -5562,13 +5595,11 @@ unpack_row(RELAY_LOG_INFO *rli,
for ( ; *field_ptr ; ++field_ptr)
{
uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG;
+ Field *const f= *field_ptr;
- DBUG_PRINT("debug", ("flags = 0x%x, mask = 0x%x, flags & mask = 0x%x",
- (*field_ptr)->flags, mask,
- (*field_ptr)->flags & mask));
-
- if (event_type == WRITE_ROWS_EVENT &&
- ((*field_ptr)->flags & mask) == mask)
+ DBUG_PRINT("info", ("processing column '%s' @ 0x%lx", f->field_name,
+ (long) f->ptr));
+ if (event_type == WRITE_ROWS_EVENT && (f->flags & mask) == mask)
{
slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD,
"Field `%s` of table `%s`.`%s` "
@@ -5578,10 +5609,10 @@ unpack_row(RELAY_LOG_INFO *rli,
error = ER_NO_DEFAULT_FOR_FIELD;
}
else
- (*field_ptr)->set_default();
+ f->set_default();
}
- return error;
+ DBUG_RETURN(error);
}
int Rows_log_event::exec_event(st_relay_log_info *rli)
@@ -5689,12 +5720,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
We also invalidate the query cache for all the tables, since
they will now be changed.
*/
-
TABLE_LIST *ptr;
for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
{
rli->m_table_map.set_table(ptr->table_id, ptr->table);
- rli->touching_table(ptr->db, ptr->table_name, ptr->table_id);
}
#ifdef HAVE_QUERY_CACHE
query_cache.invalidate_locked_for_write(rli->tables_to_lock);
@@ -5747,7 +5776,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
if ((error= do_prepare_row(thd, rli, table, row_start, &row_end)))
break; // We should perform the after-row operation even in
// the case of error
-
+
DBUG_ASSERT(row_end != NULL); // cannot happen
DBUG_ASSERT(row_end <= (const char*)m_rows_end);
@@ -5803,9 +5832,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
STMT_END_F.
For now we code, knowing that error is not skippable and so slave SQL
thread is certainly going to stop.
+ rollback at the caller along with sbr.
*/
thd->reset_current_stmt_binlog_row_based();
- rli->cleanup_context(thd, 1);
+ rli->cleanup_context(thd, 0); /* rollback at caller in step with sbr */
thd->query_error= 1;
DBUG_RETURN(error);
}
@@ -6044,10 +6074,16 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
uint8 common_header_len= description_event->common_header_len;
uint8 post_header_len= description_event->post_header_len[TABLE_MAP_EVENT-1];
- DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d",
+ DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
event_len, common_header_len, post_header_len));
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
DBUG_DUMP("event buffer", buf, event_len);
+#endif
/* Read the post-header */
const char *post_start= buf + common_header_len;
@@ -6086,10 +6122,10 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
uchar *ptr_after_colcnt= (uchar*) ptr_colcnt;
m_colcnt= net_field_length(&ptr_after_colcnt);
- DBUG_PRINT("info",("m_dblen=%d off=%d m_tbllen=%d off=%d m_colcnt=%d off=%d",
- m_dblen, ptr_dblen-(const byte*)vpart,
- m_tbllen, ptr_tbllen-(const byte*)vpart,
- m_colcnt, ptr_colcnt-(const byte*)vpart));
+ DBUG_PRINT("info",("m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld",
+ m_dblen, (long) (ptr_dblen-(const byte*)vpart),
+ m_tbllen, (long) (ptr_tbllen-(const byte*)vpart),
+ m_colcnt, (long) (ptr_colcnt-(const byte*)vpart)));
/* Allocate mem for all fields in one go. If fails, catched in is_valid() */
m_memory= my_multi_malloc(MYF(MY_WME),
@@ -6230,8 +6266,7 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
/*
We record in the slave's information that the table should be
- locked by linking the table into the list of tables to lock, and
- tell the RLI that we are touching a table.
+ locked by linking the table into the list of tables to lock.
*/
table_list->next_global= table_list->next_local= rli->tables_to_lock;
rli->tables_to_lock= table_list;
@@ -6423,17 +6458,15 @@ int Write_rows_log_event::do_after_row_operations(TABLE *table, int error)
int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
TABLE *table,
- char const *row_start,
- char const **row_end)
+ char const *const row_start,
+ char const **const row_end)
{
DBUG_ASSERT(table != NULL);
DBUG_ASSERT(row_start && row_end);
int error;
- error= unpack_row(rli,
- table, m_width, table->record[0],
- row_start, &m_cols, row_end, &m_master_reclength,
- table->write_set, WRITE_ROWS_EVENT);
+ error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end,
+ &m_master_reclength, table->write_set, WRITE_ROWS_EVENT);
bitmap_copy(table->read_set, table->write_set);
return error;
}
@@ -6494,11 +6527,11 @@ copy_extra_record_fields(TABLE *table,
my_size_t master_reclength,
my_ptrdiff_t master_fields)
{
- DBUG_PRINT("info", ("Copying to %p "
- "from field %d at offset %u "
- "to field %d at offset %u",
- table->record[0],
- master_fields, master_reclength,
+ DBUG_PRINT("info", ("Copying to 0x%lx "
+ "from field %lu at offset %lu "
+ "to field %d at offset %lu",
+ (long) table->record[0],
+ (ulong) master_fields, (ulong) master_reclength,
table->s->fields, table->s->reclength));
/*
Copying the extra fields of the slave that does not exist on
@@ -6595,6 +6628,11 @@ replace_record(THD *thd, TABLE *table,
while ((error= table->file->ha_write_row(table->record[0])))
{
+ if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT)
+ {
+ table->file->print_error(error, MYF(0)); /* to check at exec_relay_log_event */
+ DBUG_RETURN(error);
+ }
if ((keynum= table->file->get_dup_key(error)) < 0)
{
/* We failed to retrieve the duplicate key */
@@ -6649,7 +6687,7 @@ replace_record(THD *thd, TABLE *table,
present on the master from table->record[1], if there are any.
*/
copy_extra_record_fields(table, master_reclength, master_fields);
-
+
/*
REPLACE is defined as either INSERT or DELETE + INSERT. If
possible, we can replace it with an UPDATE, but that will not
@@ -6728,8 +6766,26 @@ static bool record_compare(TABLE *table)
/*
Find the row given by 'key', if the table has keys, or else use a table scan
- to find (and fetch) the row. If the engine allows random access of the
- records, a combination of position() and rnd_pos() will be used.
+ to find (and fetch) the row.
+
+ If the engine allows random access of the records, a combination of
+ position() and rnd_pos() will be used.
+
+ @param table Pointer to table to search
+ @param key Pointer to key to use for search, if table has key
+
+ @pre <code>table->record[0]</code> shall contain the row to locate
+ and <code>key</code> shall contain a key to use for searching, if
+ the engine has a key.
+
+ @post If the return value is zero, <code>table->record[1]</code>
+ will contain the fetched row and the internal "cursor" will refer to
+ the row. If the return value is non-zero,
+ <code>table->record[1]</code> is undefined. In either case,
+ <code>table->record[0]</code> is undefined.
+
+ @return Zero if the row was successfully fetched into
+ <code>table->record[1]</code>, error code otherwise.
*/
static int find_and_fetch_row(TABLE *table, byte *key)
@@ -6749,13 +6805,28 @@ static int find_and_fetch_row(TABLE *table, byte *key)
row reference using the position() member function (it will be
stored in table->file->ref) and the use rnd_pos() to position
the "cursor" (i.e., record[0] in this case) at the correct row.
+
+ TODO: Add a check that the correct record has been fetched by
+ comparing with the original record. Take into account that the
+ record on the master and slave can be of different
+ length. Something along these lines should work:
+
+ ADD>>> store_record(table,record[1]);
+ int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0],
+ table->s->reclength) == 0);
+
*/
table->file->position(table->record[0]);
- DBUG_RETURN(table->file->rnd_pos(table->record[0], table->file->ref));
+ int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ /*
+ rnd_pos() returns the record in table->record[0], so we have to
+ move it to table->record[1].
+ */
+ bmove_align(table->record[1], table->record[0], table->s->reclength);
+ DBUG_RETURN(error);
}
- DBUG_ASSERT(table->record[1]);
-
/* We need to retrieve all fields */
/* TODO: Move this out from this function to main loop */
table->use_all_columns();
@@ -6765,7 +6836,16 @@ static int find_and_fetch_row(TABLE *table, byte *key)
int error;
/* We have a key: search the table using the index */
if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE)))
- return error;
+ DBUG_RETURN(error);
+
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
+ DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength);
+ DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength);
+#endif
/*
We need to set the null bytes to ensure that the filler bit are
@@ -6785,6 +6865,14 @@ static int find_and_fetch_row(TABLE *table, byte *key)
DBUG_RETURN(error);
}
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
+ DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength);
+ DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength);
+#endif
/*
Below is a minor "optimization". If the key (i.e., key number
0) has the HA_NOSAME flag set, we know that we have found the
@@ -6969,8 +7057,8 @@ int Delete_rows_log_event::do_after_row_operations(TABLE *table, int error)
int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
TABLE *table,
- char const *row_start,
- char const **row_end)
+ char const *const row_start,
+ char const **const row_end)
{
int error;
DBUG_ASSERT(row_start && row_end);
@@ -6980,10 +7068,8 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
*/
DBUG_ASSERT(table->s->fields >= m_width);
- error= unpack_row(rli,
- table, m_width, table->record[0],
- row_start, &m_cols, row_end, &m_master_reclength,
- table->read_set, DELETE_ROWS_EVENT);
+ error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end,
+ &m_master_reclength, table->read_set, DELETE_ROWS_EVENT);
/*
If we will access rows using the random access method, m_key will
be set to NULL, so we do not need to make a key copy in that case.
@@ -7106,8 +7192,8 @@ int Update_rows_log_event::do_after_row_operations(TABLE *table, int error)
int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
TABLE *table,
- char const *row_start,
- char const **row_end)
+ char const *const row_start,
+ char const **const row_end)
{
int error;
DBUG_ASSERT(row_start && row_end);
@@ -7117,21 +7203,31 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
*/
DBUG_ASSERT(table->s->fields >= m_width);
+ /*
+ We need to perform some juggling below since unpack_row() always
+ unpacks into table->record[0]. For more information, see the
+ comments for unpack_row().
+ */
+
/* record[0] is the before image for the update */
- error= unpack_row(rli,
- table, m_width, table->record[0],
- row_start, &m_cols, row_end, &m_master_reclength,
- table->read_set, UPDATE_ROWS_EVENT);
- row_start = *row_end;
+ error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end,
+ &m_master_reclength, table->read_set, UPDATE_ROWS_EVENT);
+ store_record(table, record[1]);
+ char const *next_start = *row_end;
/* m_after_image is the after image for the update */
- error= unpack_row(rli,
- table, m_width, m_after_image,
- row_start, &m_cols, row_end, &m_master_reclength,
- table->write_set, UPDATE_ROWS_EVENT);
+ error= unpack_row(rli, table, m_width, next_start, &m_cols, row_end,
+ &m_master_reclength, table->write_set, UPDATE_ROWS_EVENT);
+ bmove_align(m_after_image, table->record[0], table->s->reclength);
+ restore_record(table, record[1]);
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
DBUG_DUMP("record[0]", (const char *)table->record[0], table->s->reclength);
DBUG_DUMP("m_after_image", (const char *)m_after_image, table->s->reclength);
-
+#endif
/*
If we will access rows using the random access method, m_key will
diff --git a/sql/log_event.h b/sql/log_event.h
index 81ce2f18b4d..c3f015e723c 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -200,8 +200,26 @@ struct sql_ex_info
#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)
#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
-/*
- Event header offsets;
+/*
+ Max number of possible extra bytes in a replication event compared to a
+ packet (i.e. a query) sent from client to master;
+ First, an auxiliary log_event status vars estimation:
+*/
+#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */ + \
+ 8 /* sql mode */ + \
+ 1 + 1 + 255 /* catalog */ + \
+ 4 /* autoinc */ + \
+ 6 /* charset */ + \
+ MAX_TIME_ZONE_NAME_LENGTH)
+#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
+ LOG_EVENT_HEADER_LEN + /* write_header */ \
+ QUERY_HEADER_LEN + /* write_data */ \
+ EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
+ MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
+ NAME_LEN + 1)
+
+/*
+ Event header offsets;
these point to places inside the fixed header.
*/
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b0947249439..2a596a673f7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -105,6 +105,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
+enum Derivation
+{
+ DERIVATION_IGNORABLE= 5,
+ DERIVATION_COERCIBLE= 4,
+ DERIVATION_SYSCONST= 3,
+ DERIVATION_IMPLICIT= 2,
+ DERIVATION_NONE= 1,
+ DERIVATION_EXPLICIT= 0
+};
+
+
typedef struct my_locale_st
{
const char *name;
@@ -1423,7 +1434,8 @@ void print_plan(JOIN* join,uint idx, double record_count, double read_time,
#endif
void mysql_print_status();
/* key.cc */
-int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length);
+int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
+ uint *key_length);
void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
void key_restore(byte *to_record, byte *from_key, KEY *key_info,
uint key_length);
@@ -1812,7 +1824,7 @@ int create_frm(THD *thd, const char *name, const char *db, const char *table,
HA_CREATE_INFO *create_info, uint keys);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
int rename_file_ext(const char * from,const char * to,const char * ext);
-bool check_db_name(char *db);
+bool check_db_name(LEX_STRING *db);
bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
char *get_field(MEM_ROOT *mem, Field *field);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 5d28d0663e7..83ac6425f2b 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1610,7 +1610,7 @@ static void network_init(void)
if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
{
sql_print_error("The socket file path is too long (> %u): %s",
- sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
+ (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unireg_abort(1);
}
if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -2121,7 +2121,7 @@ the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n",
#ifdef HAVE_STACKTRACE
if (!(test_flags & TEST_NO_STACKTRACE))
{
- fprintf(stderr,"thd=%p\n",thd);
+ fprintf(stderr,"thd: 0x%lx\n",(long) thd);
print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
thread_stack);
}
@@ -3149,11 +3149,6 @@ with --log-bin instead.");
}
if (global_system_variables.binlog_format == BINLOG_FORMAT_UNSPEC)
{
-#if defined(HAVE_NDB_BINLOG) && defined(HAVE_ROW_BASED_REPLICATION)
- if (opt_bin_log && have_ndbcluster == SHOW_OPTION_YES)
- global_system_variables.binlog_format= BINLOG_FORMAT_ROW;
- else
-#endif
#if defined(HAVE_ROW_BASED_REPLICATION)
global_system_variables.binlog_format= BINLOG_FORMAT_MIXED;
#else
@@ -3213,7 +3208,7 @@ server.");
using_update_log=1;
}
- if (plugin_init(0))
+ if (plugin_init(opt_bootstrap))
{
sql_print_error("Failed to init plugins.");
return 1;
@@ -3531,7 +3526,7 @@ int main(int argc, char **argv)
if (stack_size && stack_size < thread_stack)
{
if (global_system_variables.log_warnings)
- sql_print_warning("Asked for %ld thread stack, but got %ld",
+ sql_print_warning("Asked for %lu thread stack, but got %ld",
thread_stack, (long) stack_size);
#if defined(__ia64__) || defined(__ia64)
thread_stack= stack_size*2;
@@ -4077,7 +4072,7 @@ static void create_new_thread(THD *thd)
int error;
thread_created++;
threads.append(thd);
- DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
+ DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
thd->connect_time = time(NULL);
if ((error=pthread_create(&thd->real_id,&connection_attrib,
handle_one_connection,
@@ -5341,7 +5336,8 @@ master-ssl",
(gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \
--skip-merge.",
- (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
+ 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
diff --git a/sql/mysqld.cc.rej b/sql/mysqld.cc.rej
new file mode 100644
index 00000000000..62f0357622d
--- /dev/null
+++ b/sql/mysqld.cc.rej
@@ -0,0 +1,17 @@
+***************
+*** 5316,5322 ****
+ (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \
+ --skip-merge.",
+! (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0},
+ {"myisam-recover", OPT_MYISAM_RECOVER,
+ "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
+ (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
+--- 5336,5342 ----
+ (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \
+ --skip-merge.",
+! (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"myisam-recover", OPT_MYISAM_RECOVER,
+ "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
+ (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index a55fef5555c..ec4c4675e76 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -809,7 +809,7 @@ my_real_read(NET *net, ulong *complen)
{
my_bool interrupted = vio_should_retry(net->vio);
- DBUG_PRINT("info",("vio_read returned %d, errno: %d",
+ DBUG_PRINT("info",("vio_read returned %ld, errno: %d",
length, vio_errno(net->vio)));
#if !defined(__WIN__) || defined(MYSQL_SERVER)
/*
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 79b3e023a5f..1d6b384df35 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1003,7 +1003,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
range_end();
if (free_file)
{
- DBUG_PRINT("info", ("Freeing separate handler %p (free=%d)", file,
+ DBUG_PRINT("info", ("Freeing separate handler 0x%lx (free: %d)", (long) file,
free_file));
file->ha_external_lock(current_thd, F_UNLCK);
file->close();
@@ -2011,7 +2011,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
double scan_time;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
- keys_to_use.to_ulonglong(), (ulong) prev_tables,
+ (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables));
DBUG_PRINT("info", ("records: %lu", (ulong) head->file->stats.records));
delete quick;
@@ -3396,7 +3396,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records)));
if (busy_blocks < 1.0)
busy_blocks= 1.0;
- DBUG_PRINT("info",("sweep: nblocks=%g, busy_blocks=%g", n_blocks,
+ DBUG_PRINT("info",("sweep: nblocks: %g, busy_blocks: %g", n_blocks,
busy_blocks));
/*
Disabled: Bail out if # of blocks to read is bigger than # of blocks in
@@ -3420,7 +3420,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
result= busy_blocks;
}
}
- DBUG_PRINT("info",("returning cost=%g", result));
+ DBUG_PRINT("return",("cost: %g", result));
DBUG_RETURN(result);
}
@@ -3514,7 +3514,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
ha_rows roru_total_records;
double roru_intersect_part= 1.0;
DBUG_ENTER("get_best_disjunct_quick");
- DBUG_PRINT("info", ("Full table scan cost =%g", read_time));
+ DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root,
sizeof(TRP_RANGE*)*
@@ -3558,7 +3558,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
non_cpk_scan_records += (*cur_child)->records;
}
- DBUG_PRINT("info", ("index_merge scans cost=%g", imerge_cost));
+ DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost));
if (imerge_too_expensive || (imerge_cost > read_time) ||
(non_cpk_scan_records+cpk_scan_records >= param->table->file->stats.records) &&
read_time != DBL_MAX)
@@ -4172,7 +4172,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
DBUG_PRINT("info", ("Current out_rows= %g", info->out_rows));
DBUG_PRINT("info", ("Adding scan on %s",
info->param->table->key_info[ror_scan->keynr].name));
- DBUG_PRINT("info", ("is_cpk_scan=%d",is_cpk_scan));
+ DBUG_PRINT("info", ("is_cpk_scan: %d",is_cpk_scan));
selectivity_mult = ror_scan_selectivity(info, ror_scan);
if (selectivity_mult == 1.0)
@@ -9700,8 +9700,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
*records= num_groups;
DBUG_PRINT("info",
- ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u",
- table_records, keys_per_block, keys_per_group, *records,
+ ("table rows: %u keys/block: %u keys/group: %u result rows: %lu blocks: %u",
+ table_records, keys_per_block, keys_per_group, (ulong) *records,
num_blocks));
DBUG_VOID_RETURN;
}
@@ -10814,7 +10814,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
if (!tmp.length())
tmp.append(STRING_WITH_LEN("(empty)"));
- DBUG_PRINT("info", ("SEL_TREE %p (%s) scans:%s", tree, msg, tmp.ptr()));
+ DBUG_PRINT("info", ("SEL_TREE: 0x%lx (%s) scans: %s", (long) tree, msg, tmp.ptr()));
DBUG_VOID_RETURN;
}
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index 0071d59242e..0a2d4012af4 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -368,32 +368,33 @@ my_bool rename_in_schema_file(const char *schema, const char *old_name,
{
char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN];
- strxnmov(old_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/",
- old_name, reg_ext, NullS);
- (void) unpack_filename(old_path, old_path);
-
- strxnmov(new_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/",
- new_name, reg_ext, NullS);
- (void) unpack_filename(new_path, new_path);
+ build_table_filename(old_path, sizeof(old_path) - 1,
+ schema, old_name, reg_ext, 0);
+ build_table_filename(new_path, sizeof(new_path) - 1,
+ schema, new_name, reg_ext, 0);
if (my_rename(old_path, new_path, MYF(MY_WME)))
return 1;
/* check if arc_dir exists */
- strxnmov(arc_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/arc", NullS);
- (void) unpack_filename(arc_path, arc_path);
+ build_table_filename(arc_path, sizeof(arc_path) - 1, schema, "arc", "", 0);
if (revision > 0 && !access(arc_path, F_OK))
{
+ char old_name_buf[FN_REFLEN], new_name_buf[FN_REFLEN];
ulonglong limit= ((revision > num_view_backups) ?
revision - num_view_backups : 0);
+
+ VOID(tablename_to_filename(old_name, old_name_buf, sizeof(old_name_buf)));
+ VOID(tablename_to_filename(new_name, new_name_buf, sizeof(new_name_buf)));
+
for (; revision > limit ; revision--)
{
my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu",
- arc_path, old_name, reg_ext, (ulong)revision);
+ arc_path, old_name_buf, reg_ext, (ulong) revision);
(void) unpack_filename(old_path, old_path);
my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu",
- arc_path, new_name, reg_ext, (ulong)revision);
+ arc_path, new_name_buf, reg_ext, (ulong) revision);
(void) unpack_filename(new_path, new_path);
my_rename(old_path, new_path, MYF(0));
}
diff --git a/sql/parse_file.h b/sql/parse_file.h
index 5fb65b4c7ec..0a02bf7eb75 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -106,21 +106,4 @@ public:
MEM_ROOT *mem_root,
bool bad_format_errors);
};
-
-
-/*
- Custom version of standard offsetof() macro which can be used to get
- offsets of members in class for non-POD types (according to the current
- version of C++ standard offsetof() macro can't be used in such cases and
- attempt to do so causes warnings to be emitted, OTOH in many cases it is
- still OK to assume that all instances of the class has the same offsets
- for the same members).
-
- This is temporary solution which should be removed once File_parser class
- and related routines are refactored.
-*/
-
-#define my_offsetof(TYPE, MEMBER) \
- ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
-
#endif /* _PARSE_FILE_H_ */
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 66e2aa1c31c..762fcfb7a6a 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -564,8 +564,8 @@ err:
mysql_free_result(res);
if (error)
{
- sql_print_error("While trying to obtain the list of slaves from the master \
-'%s:%d', user '%s' got the following error: '%s'",
+ sql_print_error("While trying to obtain the list of slaves from the master "
+ "'%s:%d', user '%s' got the following error: '%s'",
mi->host, mi->port, mi->user, error);
DBUG_RETURN(1);
}
@@ -962,7 +962,7 @@ bool load_master_data(THD* thd)
Cancel the previous START SLAVE UNTIL, as the fact to download
a new copy logically makes UNTIL irrelevant.
*/
- clear_until_condition(&active_mi->rli);
+ active_mi->rli.clear_until_condition();
/*
No need to update rli.event* coordinates, they will be when the slave
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index 5a74fd58755..3a0fca4dfa5 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -39,6 +39,8 @@ injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
m_start_pos.m_file_pos= log_info.pos;
begin_trans(m_thd);
+
+ thd->set_current_stmt_binlog_row_based();
}
injector::transaction::~transaction()
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
new file mode 100644
index 00000000000..c89c8aa131e
--- /dev/null
+++ b/sql/rpl_mi.cc
@@ -0,0 +1,386 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 <my_global.h> // For HAVE_REPLICATION
+#include "mysql_priv.h"
+#include <my_dir.h>
+
+#include "rpl_mi.h"
+
+#ifdef HAVE_REPLICATION
+
+
+// Defined in slave.cc
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+ const char *default_val);
+
+MASTER_INFO::MASTER_INFO()
+ :ssl(0), fd(-1), io_thd(0), inited(0),
+ abort_slave(0),slave_running(0), slave_run_id(0)
+{
+ host[0] = 0; user[0] = 0; password[0] = 0;
+ ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
+ ssl_cipher[0]= 0; ssl_key[0]= 0;
+
+ bzero((char*) &file, sizeof(file));
+ pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&data_cond, NULL);
+ pthread_cond_init(&start_cond, NULL);
+ pthread_cond_init(&stop_cond, NULL);
+}
+
+MASTER_INFO::~MASTER_INFO()
+{
+ pthread_mutex_destroy(&run_lock);
+ pthread_mutex_destroy(&data_lock);
+ pthread_cond_destroy(&data_cond);
+ pthread_cond_destroy(&start_cond);
+ pthread_cond_destroy(&stop_cond);
+}
+
+
+void init_master_info_with_options(MASTER_INFO* mi)
+{
+ DBUG_ENTER("init_master_info_with_options");
+
+ mi->master_log_name[0] = 0;
+ mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number
+
+ if (master_host)
+ strmake(mi->host, master_host, sizeof(mi->host) - 1);
+ if (master_user)
+ strmake(mi->user, master_user, sizeof(mi->user) - 1);
+ if (master_password)
+ strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
+ mi->port = master_port;
+ mi->connect_retry = master_connect_retry;
+
+ mi->ssl= master_ssl;
+ if (master_ssl_ca)
+ strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1);
+ if (master_ssl_capath)
+ strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1);
+ if (master_ssl_cert)
+ strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1);
+ if (master_ssl_cipher)
+ strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1);
+ if (master_ssl_key)
+ strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1);
+ DBUG_VOID_RETURN;
+}
+
+
+#define LINES_IN_MASTER_INFO_WITH_SSL 14
+
+
+int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file,
+ int thread_mask)
+{
+ int fd,error;
+ char fname[FN_REFLEN+128];
+ DBUG_ENTER("init_master_info");
+
+ if (mi->inited)
+ {
+ /*
+ We have to reset read position of relay-log-bin as we may have
+ already been reading from 'hotlog' when the slave was stopped
+ last time. If this case pos_in_file would be set and we would
+ get a crash when trying to read the signature for the binary
+ relay log.
+
+ We only rewind the read position if we are starting the SQL
+ thread. The handle_slave_sql thread assumes that the read
+ position is at the beginning of the file, and will read the
+ "signature" and then fast-forward to the last position read.
+ */
+ if (thread_mask & SLAVE_SQL)
+ {
+ my_b_seek(mi->rli.cur_log, (my_off_t) 0);
+ }
+ DBUG_RETURN(0);
+ }
+
+ mi->mysql=0;
+ mi->file_id=1;
+ fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
+
+ /*
+ We need a mutex while we are changing master info parameters to
+ keep other threads from reading bogus info
+ */
+
+ pthread_mutex_lock(&mi->data_lock);
+ fd = mi->fd;
+
+ /* does master.info exist ? */
+
+ if (access(fname,F_OK))
+ {
+ if (abort_if_no_master_info_file)
+ {
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(0);
+ }
+ /*
+ if someone removed the file from underneath our feet, just close
+ the old descriptor and re-create the old file
+ */
+ if (fd >= 0)
+ my_close(fd, MYF(MY_WME));
+ if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
+ {
+ sql_print_error("Failed to create a new master info file (\
+file '%s', errno %d)", fname, my_errno);
+ goto err;
+ }
+ if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
+ MYF(MY_WME)))
+ {
+ sql_print_error("Failed to create a cache on master info file (\
+file '%s')", fname);
+ goto err;
+ }
+
+ mi->fd = fd;
+ init_master_info_with_options(mi);
+
+ }
+ else // file exists
+ {
+ if (fd >= 0)
+ reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
+ else
+ {
+ if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
+ {
+ sql_print_error("Failed to open the existing master info file (\
+file '%s', errno %d)", fname, my_errno);
+ goto err;
+ }
+ if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
+ 0, MYF(MY_WME)))
+ {
+ sql_print_error("Failed to create a cache on master info file (\
+file '%s')", fname);
+ goto err;
+ }
+ }
+
+ mi->fd = fd;
+ int port, connect_retry, master_log_pos, ssl= 0, lines;
+ char *first_non_digit;
+
+ /*
+ Starting from 4.1.x master.info has new format. Now its
+ first line contains number of lines in file. By reading this
+ number we will be always distinguish to which version our
+ master.info corresponds to. We can't simply count lines in
+ file since versions before 4.1.x could generate files with more
+ lines than needed.
+ If first line doesn't contain a number or contain number less than
+ 14 then such file is treated like file from pre 4.1.1 version.
+ There is no ambiguity when reading an old master.info, as before
+ 4.1.1, the first line contained the binlog's name, which is either
+ empty or has an extension (contains a '.'), so can't be confused
+ with an integer.
+
+ So we're just reading first line and trying to figure which version
+ is this.
+ */
+
+ /*
+ The first row is temporarily stored in mi->master_log_name,
+ if it is line count and not binlog name (new format) it will be
+ overwritten by the second row later.
+ */
+ if (init_strvar_from_file(mi->master_log_name,
+ sizeof(mi->master_log_name), &mi->file,
+ ""))
+ goto errwithmsg;
+
+ lines= strtoul(mi->master_log_name, &first_non_digit, 10);
+
+ if (mi->master_log_name[0]!='\0' &&
+ *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
+ { // Seems to be new format
+ if (init_strvar_from_file(mi->master_log_name,
+ sizeof(mi->master_log_name), &mi->file, ""))
+ goto errwithmsg;
+ }
+ else
+ lines= 7;
+
+ if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
+ init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
+ master_host) ||
+ init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
+ master_user) ||
+ init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
+ &mi->file, master_password) ||
+ init_intvar_from_file(&port, &mi->file, master_port) ||
+ init_intvar_from_file(&connect_retry, &mi->file,
+ master_connect_retry))
+ goto errwithmsg;
+
+ /*
+ If file has ssl part use it even if we have server without
+ SSL support. But these option will be ignored later when
+ slave will try connect to master, so in this case warning
+ is printed.
+ */
+ if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
+ (init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
+ init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
+ &mi->file, master_ssl_ca) ||
+ init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
+ &mi->file, master_ssl_capath) ||
+ init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
+ &mi->file, master_ssl_cert) ||
+ init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
+ &mi->file, master_ssl_cipher) ||
+ init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
+ &mi->file, master_ssl_key)))
+ goto errwithmsg;
+#ifndef HAVE_OPENSSL
+ if (ssl)
+ sql_print_warning("SSL information in the master info file "
+ "('%s') are ignored because this MySQL slave was compiled "
+ "without SSL support.", fname);
+#endif /* HAVE_OPENSSL */
+
+ /*
+ This has to be handled here as init_intvar_from_file can't handle
+ my_off_t types
+ */
+ mi->master_log_pos= (my_off_t) master_log_pos;
+ mi->port= (uint) port;
+ mi->connect_retry= (uint) connect_retry;
+ mi->ssl= (my_bool) ssl;
+ }
+ DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
+ mi->master_log_name,
+ (ulong) mi->master_log_pos));
+
+ mi->rli.mi = mi;
+ if (init_relay_log_info(&mi->rli, slave_info_fname))
+ goto err;
+
+ mi->inited = 1;
+ // now change cache READ -> WRITE - must do this before flush_master_info
+ reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
+ if ((error=test(flush_master_info(mi, 1))))
+ sql_print_error("Failed to flush master info file");
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(error);
+
+errwithmsg:
+ sql_print_error("Error reading master configuration");
+
+err:
+ if (fd >= 0)
+ {
+ my_close(fd, MYF(0));
+ end_io_cache(&mi->file);
+ }
+ mi->fd= -1;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(1);
+}
+
+
+/*
+ RETURN
+ 2 - flush relay log failed
+ 1 - flush master info failed
+ 0 - all ok
+*/
+int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
+{
+ IO_CACHE* file = &mi->file;
+ char lbuf[22];
+ DBUG_ENTER("flush_master_info");
+ DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
+
+ /*
+ Flush the relay log to disk. If we don't do it, then the relay log while
+ have some part (its last kilobytes) in memory only, so if the slave server
+ dies now, with, say, from master's position 100 to 150 in memory only (not
+ on disk), and with position 150 in master.info, then when the slave
+ restarts, the I/O thread will fetch binlogs from 150, so in the relay log
+ we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
+ SQL thread will jump from 100 to 150, and replication will silently break.
+
+ When we come to this place in code, relay log may or not be initialized;
+ the caller is responsible for setting 'flush_relay_log_cache' accordingly.
+ */
+ if (flush_relay_log_cache &&
+ flush_io_cache(mi->rli.relay_log.get_log_file()))
+ DBUG_RETURN(2);
+
+ /*
+ We flushed the relay log BEFORE the master.info file, because if we crash
+ now, we will get a duplicate event in the relay log at restart. If we
+ flushed in the other order, we would get a hole in the relay log.
+ And duplicate is better than hole (with a duplicate, in later versions we
+ can add detection and scrap one event; with a hole there's nothing we can
+ do).
+ */
+
+ /*
+ In certain cases this code may create master.info files that seems
+ corrupted, because of extra lines filled with garbage in the end
+ file (this happens if new contents take less space than previous
+ contents of file). But because of number of lines in the first line
+ of file we don't care about this garbage.
+ */
+
+ my_b_seek(file, 0L);
+ my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n",
+ LINES_IN_MASTER_INFO_WITH_SSL,
+ mi->master_log_name, llstr(mi->master_log_pos, lbuf),
+ mi->host, mi->user,
+ mi->password, mi->port, mi->connect_retry,
+ (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
+ mi->ssl_cipher, mi->ssl_key);
+ DBUG_RETURN(-flush_io_cache(file));
+}
+
+
+void end_master_info(MASTER_INFO* mi)
+{
+ DBUG_ENTER("end_master_info");
+
+ if (!mi->inited)
+ DBUG_VOID_RETURN;
+ end_relay_log_info(&mi->rli);
+ if (mi->fd >= 0)
+ {
+ end_io_cache(&mi->file);
+ (void)my_close(mi->fd, MYF(MY_WME));
+ mi->fd = -1;
+ }
+ mi->inited = 0;
+
+ DBUG_VOID_RETURN;
+}
+
+
+#endif /* HAVE_REPLICATION */
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
new file mode 100644
index 00000000000..f0a7d6681fe
--- /dev/null
+++ b/sql/rpl_mi.h
@@ -0,0 +1,110 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 RPL_MI_H
+#define RPL_MI_H
+
+#ifdef HAVE_REPLICATION
+
+/*****************************************************************************
+
+ Replication IO Thread
+
+ MASTER_INFO contains:
+ - information about how to connect to a master
+ - current master log name
+ - current master log offset
+ - misc control variables
+
+ MASTER_INFO is initialized once from the master.info file if such
+ exists. Otherwise, data members corresponding to master.info fields
+ are initialized with defaults specified by master-* options. The
+ initialization is done through init_master_info() call.
+
+ The format of master.info file:
+
+ log_name
+ log_pos
+ master_host
+ master_user
+ master_pass
+ master_port
+ master_connect_retry
+
+ To write out the contents of master.info file to disk ( needed every
+ time we read and queue data from the master ), a call to
+ flush_master_info() is required.
+
+ To clean up, call end_master_info()
+
+*****************************************************************************/
+
+class MASTER_INFO
+{
+ public:
+ MASTER_INFO();
+ ~MASTER_INFO();
+
+ /* the variables below are needed because we can change masters on the fly */
+ char master_log_name[FN_REFLEN];
+ char host[HOSTNAME_LENGTH+1];
+ char user[USERNAME_LENGTH+1];
+ char password[MAX_PASSWORD_LENGTH+1];
+ my_bool ssl; // enables use of SSL connection if true
+ char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
+ char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
+
+ my_off_t master_log_pos;
+ File fd; // we keep the file open, so we need to remember the file pointer
+ IO_CACHE file;
+
+ pthread_mutex_t data_lock,run_lock;
+ pthread_cond_t data_cond,start_cond,stop_cond;
+ THD *io_thd;
+ MYSQL* mysql;
+ uint32 file_id; /* for 3.23 load data infile */
+ RELAY_LOG_INFO rli;
+ uint port;
+ uint connect_retry;
+#ifndef DBUG_OFF
+ int events_till_disconnect;
+#endif
+ bool inited;
+ volatile bool abort_slave;
+ volatile uint slave_running;
+ volatile ulong slave_run_id;
+ /*
+ The difference in seconds between the clock of the master and the clock of
+ the slave (second - first). It must be signed as it may be <0 or >0.
+ clock_diff_with_master is computed when the I/O thread starts; for this the
+ I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
+ "how late the slave is compared to the master" is computed like this:
+ clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
+
+ */
+ long clock_diff_with_master;
+};
+
+void init_master_info_with_options(MASTER_INFO* mi);
+int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file,
+ int thread_mask);
+void end_master_info(MASTER_INFO* mi);
+int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache);
+
+#endif /* HAVE_REPLICATION */
+#endif /* RPL_MI_H */
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
new file mode 100644
index 00000000000..a2edb9dc8a8
--- /dev/null
+++ b/sql/rpl_rli.cc
@@ -0,0 +1,1112 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 "mysql_priv.h"
+
+#include "rpl_rli.h"
+#include <my_dir.h> // For MY_STAT
+#include "sql_repl.h" // For check_binlog_magic
+
+static int count_relay_log_space(RELAY_LOG_INFO* rli);
+
+// Defined in slave.cc
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+ const char *default_val);
+
+
+st_relay_log_info::st_relay_log_info()
+ :no_storage(FALSE), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
+ cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0),
+ ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0),
+ abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0),
+ inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
+ until_log_pos(0), retried_trans(0),
+ tables_to_lock(0), tables_to_lock_count(0),
+ unsafe_to_stop_at(0)
+{
+ DBUG_ENTER("st_relay_log_info::st_relay_log_info");
+
+ group_relay_log_name[0]= event_relay_log_name[0]=
+ group_master_log_name[0]= 0;
+ last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0;
+ bzero((char*) &info_file, sizeof(info_file));
+ bzero((char*) &cache_buf, sizeof(cache_buf));
+ cached_charset_invalidate();
+ pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&data_cond, NULL);
+ pthread_cond_init(&start_cond, NULL);
+ pthread_cond_init(&stop_cond, NULL);
+ pthread_cond_init(&log_space_cond, NULL);
+ relay_log.init_pthread_objects();
+ DBUG_VOID_RETURN;
+}
+
+
+st_relay_log_info::~st_relay_log_info()
+{
+ DBUG_ENTER("st_relay_log_info::~st_relay_log_info");
+
+ pthread_mutex_destroy(&run_lock);
+ pthread_mutex_destroy(&data_lock);
+ pthread_mutex_destroy(&log_space_lock);
+ pthread_cond_destroy(&data_cond);
+ pthread_cond_destroy(&start_cond);
+ pthread_cond_destroy(&stop_cond);
+ pthread_cond_destroy(&log_space_cond);
+ relay_log.cleanup();
+ DBUG_VOID_RETURN;
+}
+
+
+int init_relay_log_info(RELAY_LOG_INFO* rli,
+ const char* info_fname)
+{
+ char fname[FN_REFLEN+128];
+ int info_fd;
+ const char* msg = 0;
+ int error = 0;
+ DBUG_ENTER("init_relay_log_info");
+ DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage
+
+ if (rli->inited) // Set if this function called
+ DBUG_RETURN(0);
+ fn_format(fname, info_fname, mysql_data_home, "", 4+32);
+ pthread_mutex_lock(&rli->data_lock);
+ info_fd = rli->info_fd;
+ rli->cur_log_fd = -1;
+ rli->slave_skip_counter=0;
+ rli->abort_pos_wait=0;
+ rli->log_space_limit= relay_log_space_limit;
+ rli->log_space_total= 0;
+ rli->tables_to_lock= 0;
+ rli->tables_to_lock_count= 0;
+
+ /*
+ The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
+ Note that the I/O thread flushes it to disk after writing every
+ event, in flush_master_info(mi, 1).
+ */
+
+ /*
+ For the maximum log size, we choose max_relay_log_size if it is
+ non-zero, max_binlog_size otherwise. If later the user does SET
+ GLOBAL on one of these variables, fix_max_binlog_size and
+ fix_max_relay_log_size will reconsider the choice (for example
+ if the user changes max_relay_log_size to zero, we have to
+ switch to using max_binlog_size for the relay log) and update
+ rli->relay_log.max_size (and mysql_bin_log.max_size).
+ */
+ {
+ char buf[FN_REFLEN];
+ const char *ln;
+ static bool name_warning_sent= 0;
+ ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
+ 1, buf);
+ /* We send the warning only at startup, not after every RESET SLAVE */
+ if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
+ {
+ /*
+ User didn't give us info to name the relay log index file.
+ Picking `hostname`-relay-bin.index like we do, causes replication to
+ fail if this slave's hostname is changed later. So, we would like to
+ instead require a name. But as we don't want to break many existing
+ setups, we only give warning, not error.
+ */
+ sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
+ " so replication "
+ "may break when this MySQL server acts as a "
+ "slave and has his hostname changed!! Please "
+ "use '--relay-log=%s' to avoid this problem.", ln);
+ name_warning_sent= 1;
+ }
+ /*
+ note, that if open() fails, we'll still have index file open
+ but a destructor will take care of that
+ */
+ if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
+ rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
+ (max_relay_log_size ? max_relay_log_size :
+ max_binlog_size), 1))
+ {
+ pthread_mutex_unlock(&rli->data_lock);
+ sql_print_error("Failed in open_log() called from init_relay_log_info()");
+ DBUG_RETURN(1);
+ }
+ }
+
+ /* if file does not exist */
+ if (access(fname,F_OK))
+ {
+ /*
+ If someone removed the file from underneath our feet, just close
+ the old descriptor and re-create the old file
+ */
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(MY_WME));
+ if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
+ {
+ sql_print_error("Failed to create a new relay log info file (\
+file '%s', errno %d)", fname, my_errno);
+ msg= current_thd->net.last_error;
+ goto err;
+ }
+ if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+ MYF(MY_WME)))
+ {
+ sql_print_error("Failed to create a cache on relay log info file '%s'",
+ fname);
+ msg= current_thd->net.last_error;
+ goto err;
+ }
+
+ /* Init relay log with first entry in the relay index file */
+ if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
+ &msg, 0))
+ {
+ sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
+ goto err;
+ }
+ rli->group_master_log_name[0]= 0;
+ rli->group_master_log_pos= 0;
+ rli->info_fd= info_fd;
+ }
+ else // file exists
+ {
+ if (info_fd >= 0)
+ reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
+ else
+ {
+ int error=0;
+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
+ {
+ sql_print_error("\
+Failed to open the existing relay log info file '%s' (errno %d)",
+ fname, my_errno);
+ error= 1;
+ }
+ else if (init_io_cache(&rli->info_file, info_fd,
+ IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
+ {
+ sql_print_error("Failed to create a cache on relay log info file '%s'",
+ fname);
+ error= 1;
+ }
+ if (error)
+ {
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(0));
+ rli->info_fd= -1;
+ rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(1);
+ }
+ }
+
+ rli->info_fd = info_fd;
+ int relay_log_pos, master_log_pos;
+ if (init_strvar_from_file(rli->group_relay_log_name,
+ sizeof(rli->group_relay_log_name),
+ &rli->info_file, "") ||
+ init_intvar_from_file(&relay_log_pos,
+ &rli->info_file, BIN_LOG_HEADER_SIZE) ||
+ init_strvar_from_file(rli->group_master_log_name,
+ sizeof(rli->group_master_log_name),
+ &rli->info_file, "") ||
+ init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
+ {
+ msg="Error reading slave log configuration";
+ goto err;
+ }
+ strmake(rli->event_relay_log_name,rli->group_relay_log_name,
+ sizeof(rli->event_relay_log_name)-1);
+ rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
+ rli->group_master_log_pos= master_log_pos;
+
+ if (init_relay_log_pos(rli,
+ rli->group_relay_log_name,
+ rli->group_relay_log_pos,
+ 0 /* no data lock*/,
+ &msg, 0))
+ {
+ char llbuf[22];
+ sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
+ rli->group_relay_log_name,
+ llstr(rli->group_relay_log_pos, llbuf));
+ goto err;
+ }
+ }
+
+#ifndef DBUG_OFF
+ {
+ char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(rli->cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
+ DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+ DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+ }
+#endif
+
+ /*
+ Now change the cache from READ to WRITE - must do this
+ before flush_relay_log_info
+ */
+ reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
+ if ((error= flush_relay_log_info(rli)))
+ sql_print_error("Failed to flush relay log info file");
+ if (count_relay_log_space(rli))
+ {
+ msg="Error counting relay log space";
+ goto err;
+ }
+ rli->inited= 1;
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(error);
+
+err:
+ sql_print_error(msg);
+ end_io_cache(&rli->info_file);
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(0));
+ rli->info_fd= -1;
+ rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(1);
+}
+
+
+static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
+{
+ MY_STAT s;
+ DBUG_ENTER("add_relay_log");
+ if (!my_stat(linfo->log_file_name,&s,MYF(0)))
+ {
+ sql_print_error("log %s listed in the index, but failed to stat",
+ linfo->log_file_name);
+ DBUG_RETURN(1);
+ }
+ rli->log_space_total += s.st_size;
+#ifndef DBUG_OFF
+ char buf[22];
+ DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf)));
+#endif
+ DBUG_RETURN(0);
+}
+
+
+static int count_relay_log_space(RELAY_LOG_INFO* rli)
+{
+ LOG_INFO linfo;
+ DBUG_ENTER("count_relay_log_space");
+ rli->log_space_total= 0;
+ if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
+ {
+ sql_print_error("Could not find first log while counting relay log space");
+ DBUG_RETURN(1);
+ }
+ do
+ {
+ if (add_relay_log(rli,&linfo))
+ DBUG_RETURN(1);
+ } while (!rli->relay_log.find_next_log(&linfo, 1));
+ /*
+ As we have counted everything, including what may have written in a
+ preceding write, we must reset bytes_written, or we may count some space
+ twice.
+ */
+ rli->relay_log.reset_bytes_written();
+ DBUG_RETURN(0);
+}
+
+
+void st_relay_log_info::clear_slave_error()
+{
+ DBUG_ENTER("clear_slave_error");
+
+ /* Clear the errors displayed by SHOW SLAVE STATUS */
+ last_slave_error[0]= 0;
+ last_slave_errno= 0;
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Reset UNTIL condition for RELAY_LOG_INFO
+
+ SYNOPSYS
+ clear_until_condition()
+ rli - RELAY_LOG_INFO structure where UNTIL condition should be reset
+ */
+
+void st_relay_log_info::clear_until_condition()
+{
+ DBUG_ENTER("clear_until_condition");
+
+ until_condition= RELAY_LOG_INFO::UNTIL_NONE;
+ until_log_name[0]= 0;
+ until_log_pos= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Open the given relay log
+
+ SYNOPSIS
+ init_relay_log_pos()
+ rli Relay information (will be initialized)
+ log Name of relay log file to read from. NULL = First log
+ pos Position in relay log file
+ need_data_lock Set to 1 if this functions should do mutex locks
+ errmsg Store pointer to error message here
+ look_for_description_event
+ 1 if we should look for such an event. We only need
+ this when the SQL thread starts and opens an existing
+ relay log and has to execute it (possibly from an
+ offset >4); then we need to read the first event of
+ the relay log to be able to parse the events we have
+ to execute.
+
+ DESCRIPTION
+ - Close old open relay log files.
+ - If we are using the same relay log as the running IO-thread, then set
+ rli->cur_log to point to the same IO_CACHE entry.
+ - If not, open the 'log' binary file.
+
+ TODO
+ - check proper initialization of group_master_log_name/group_master_log_pos
+
+ RETURN VALUES
+ 0 ok
+ 1 error. errmsg is set to point to the error message
+*/
+
+int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
+ ulonglong pos, bool need_data_lock,
+ const char** errmsg,
+ bool look_for_description_event)
+{
+ DBUG_ENTER("init_relay_log_pos");
+ DBUG_PRINT("info", ("pos: %lu", (ulong) pos));
+
+ *errmsg=0;
+ pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
+
+ if (need_data_lock)
+ pthread_mutex_lock(&rli->data_lock);
+
+ /*
+ Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
+ is, too, and init_slave() too; these 2 functions allocate a description
+ event in init_relay_log_pos, which is not freed by the terminating SQL slave
+ thread as that thread is not started by these functions. So we have to free
+ the description_event here, in case, so that there is no memory leak in
+ running, say, CHANGE MASTER.
+ */
+ delete rli->relay_log.description_event_for_exec;
+ /*
+ By default the relay log is in binlog format 3 (4.0).
+ Even if format is 4, this will work enough to read the first event
+ (Format_desc) (remember that format 4 is just lenghtened compared to format
+ 3; format 3 is a prefix of format 4).
+ */
+ rli->relay_log.description_event_for_exec= new
+ Format_description_log_event(3);
+
+ pthread_mutex_lock(log_lock);
+
+ /* Close log file and free buffers if it's already open */
+ if (rli->cur_log_fd >= 0)
+ {
+ end_io_cache(&rli->cache_buf);
+ my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd = -1;
+ }
+
+ rli->group_relay_log_pos = rli->event_relay_log_pos = pos;
+
+ /*
+ Test to see if the previous run was with the skip of purging
+ If yes, we do not purge when we restart
+ */
+ if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1))
+ {
+ *errmsg="Could not find first log during relay log initialization";
+ goto err;
+ }
+
+ if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1))
+ {
+ *errmsg="Could not find target log during relay log initialization";
+ goto err;
+ }
+ strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->group_relay_log_name)-1);
+ strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->event_relay_log_name)-1);
+ if (rli->relay_log.is_active(rli->linfo.log_file_name))
+ {
+ /*
+ The IO thread is using this log file.
+ In this case, we will use the same IO_CACHE pointer to
+ read data as the IO thread is using to write data.
+ */
+ my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0);
+ if (check_binlog_magic(rli->cur_log,errmsg))
+ goto err;
+ rli->cur_log_old_open_count=rli->relay_log.get_open_count();
+ }
+ else
+ {
+ /*
+ Open the relay log and set rli->cur_log to point at this one
+ */
+ if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
+ rli->linfo.log_file_name,errmsg)) < 0)
+ goto err;
+ rli->cur_log = &rli->cache_buf;
+ }
+ /*
+ In all cases, check_binlog_magic() has been called so we're at offset 4 for
+ sure.
+ */
+ if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
+ {
+ Log_event* ev;
+ while (look_for_description_event)
+ {
+ /*
+ Read the possible Format_description_log_event; if position
+ was 4, no need, it will be read naturally.
+ */
+ DBUG_PRINT("info",("looking for a Format_description_log_event"));
+
+ if (my_b_tell(rli->cur_log) >= pos)
+ break;
+
+ /*
+ Because of we have rli->data_lock and log_lock, we can safely read an
+ event
+ */
+ if (!(ev=Log_event::read_log_event(rli->cur_log,0,
+ rli->relay_log.description_event_for_exec)))
+ {
+ DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
+ rli->cur_log->error));
+ if (rli->cur_log->error) /* not EOF */
+ {
+ *errmsg= "I/O error reading event at position 4";
+ goto err;
+ }
+ break;
+ }
+ else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
+ {
+ DBUG_PRINT("info",("found Format_description_log_event"));
+ delete rli->relay_log.description_event_for_exec;
+ rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
+ /*
+ As ev was returned by read_log_event, it has passed is_valid(), so
+ my_malloc() in ctor worked, no need to check again.
+ */
+ /*
+ Ok, we found a Format_description event. But it is not sure that this
+ describes the whole relay log; indeed, one can have this sequence
+ (starting from position 4):
+ Format_desc (of slave)
+ Rotate (of master)
+ Format_desc (of master)
+ So the Format_desc which really describes the rest of the relay log
+ is the 3rd event (it can't be further than that, because we rotate
+ the relay log when we queue a Rotate event from the master).
+ But what describes the Rotate is the first Format_desc.
+ So what we do is:
+ go on searching for Format_description events, until you exceed the
+ position (argument 'pos') or until you find another event than Rotate
+ or Format_desc.
+ */
+ }
+ else
+ {
+ DBUG_PRINT("info",("found event of another type=%d",
+ ev->get_type_code()));
+ look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
+ delete ev;
+ }
+ }
+ my_b_seek(rli->cur_log,(off_t)pos);
+#ifndef DBUG_OFF
+ {
+ char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(rli->cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
+ }
+#endif
+
+ }
+
+err:
+ /*
+ If we don't purge, we can't honour relay_log_space_limit ;
+ silently discard it
+ */
+ if (!relay_log_purge)
+ rli->log_space_limit= 0;
+ pthread_cond_broadcast(&rli->data_cond);
+
+ pthread_mutex_unlock(log_lock);
+
+ if (need_data_lock)
+ pthread_mutex_unlock(&rli->data_lock);
+ if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
+ *errmsg= "Invalid Format_description log event; could be out of memory";
+
+ DBUG_RETURN ((*errmsg) ? 1 : 0);
+}
+
+
+/*
+ Waits until the SQL thread reaches (has executed up to) the
+ log/position or timed out.
+
+ SYNOPSIS
+ wait_for_pos()
+ thd client thread that sent SELECT MASTER_POS_WAIT
+ log_name log name to wait for
+ log_pos position to wait for
+ timeout timeout in seconds before giving up waiting
+
+ NOTES
+ timeout is longlong whereas it should be ulong ; but this is
+ to catch if the user submitted a negative timeout.
+
+ RETURN VALUES
+ -2 improper arguments (log_pos<0)
+ or slave not running, or master info changed
+ during the function's execution,
+ or client thread killed. -2 is translated to NULL by caller
+ -1 timed out
+ >=0 number of log events the function had to wait
+ before reaching the desired log/position
+ */
+
+int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
+ longlong log_pos,
+ longlong timeout)
+{
+ int event_count = 0;
+ ulong init_abort_pos_wait;
+ int error=0;
+ struct timespec abstime; // for timeout checking
+ const char *msg;
+ DBUG_ENTER("st_relay_log_info::wait_for_pos");
+
+ if (!inited)
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu",
+ log_name->c_ptr(), (ulong) log_pos, (ulong) timeout));
+
+ set_timespec(abstime,timeout);
+ pthread_mutex_lock(&data_lock);
+ msg= thd->enter_cond(&data_cond, &data_lock,
+ "Waiting for the slave SQL thread to "
+ "advance position");
+ /*
+ This function will abort when it notices that some CHANGE MASTER or
+ RESET MASTER has changed the master info.
+ To catch this, these commands modify abort_pos_wait ; We just monitor
+ abort_pos_wait and see if it has changed.
+ Why do we have this mechanism instead of simply monitoring slave_running
+ in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that
+ the SQL thread be stopped?
+ This is becasue if someones does:
+ STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE;
+ the change may happen very quickly and we may not notice that
+ slave_running briefly switches between 1/0/1.
+ */
+ init_abort_pos_wait= abort_pos_wait;
+
+ /*
+ We'll need to
+ handle all possible log names comparisons (e.g. 999 vs 1000).
+ We use ulong for string->number conversion ; this is no
+ stronger limitation than in find_uniq_filename in sql/log.cc
+ */
+ ulong log_name_extension;
+ char log_name_tmp[FN_REFLEN]; //make a char[] from String
+
+ strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1));
+
+ char *p= fn_ext(log_name_tmp);
+ char *p_end;
+ if (!*p || log_pos<0)
+ {
+ error= -2; //means improper arguments
+ goto err;
+ }
+ // Convert 0-3 to 4
+ log_pos= max(log_pos, BIN_LOG_HEADER_SIZE);
+ /* p points to '.' */
+ log_name_extension= strtoul(++p, &p_end, 10);
+ /*
+ p_end points to the first invalid character.
+ If it equals to p, no digits were found, error.
+ If it contains '\0' it means conversion went ok.
+ */
+ if (p_end==p || *p_end)
+ {
+ error= -2;
+ goto err;
+ }
+
+ /* The "compare and wait" main loop */
+ while (!thd->killed &&
+ init_abort_pos_wait == abort_pos_wait &&
+ slave_running)
+ {
+ bool pos_reached;
+ int cmp_result= 0;
+
+ DBUG_PRINT("info",
+ ("init_abort_pos_wait: %ld abort_pos_wait: %ld",
+ init_abort_pos_wait, abort_pos_wait));
+ DBUG_PRINT("info",("group_master_log_name: '%s' pos: %lu",
+ group_master_log_name, (ulong) group_master_log_pos));
+
+ /*
+ group_master_log_name can be "", if we are just after a fresh
+ replication start or after a CHANGE MASTER TO MASTER_HOST/PORT
+ (before we have executed one Rotate event from the master) or
+ (rare) if the user is doing a weird slave setup (see next
+ paragraph). If group_master_log_name is "", we assume we don't
+ have enough info to do the comparison yet, so we just wait until
+ more data. In this case master_log_pos is always 0 except if
+ somebody (wrongly) sets this slave to be a slave of itself
+ without using --replicate-same-server-id (an unsupported
+ configuration which does nothing), then group_master_log_pos
+ will grow and group_master_log_name will stay "".
+ */
+ if (*group_master_log_name)
+ {
+ char *basename= (group_master_log_name +
+ dirname_length(group_master_log_name));
+ /*
+ First compare the parts before the extension.
+ Find the dot in the master's log basename,
+ and protect against user's input error :
+ if the names do not match up to '.' included, return error
+ */
+ char *q= (char*)(fn_ext(basename)+1);
+ if (strncmp(basename, log_name_tmp, (int)(q-basename)))
+ {
+ error= -2;
+ break;
+ }
+ // Now compare extensions.
+ char *q_end;
+ ulong group_master_log_name_extension= strtoul(q, &q_end, 10);
+ if (group_master_log_name_extension < log_name_extension)
+ cmp_result= -1 ;
+ else
+ cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ;
+
+ pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) ||
+ cmp_result > 0);
+ if (pos_reached || thd->killed)
+ break;
+ }
+
+ //wait for master update, with optional timeout.
+
+ DBUG_PRINT("info",("Waiting for master update"));
+ /*
+ We are going to pthread_cond_(timed)wait(); if the SQL thread stops it
+ will wake us up.
+ */
+ if (timeout > 0)
+ {
+ /*
+ Note that pthread_cond_timedwait checks for the timeout
+ before for the condition ; i.e. it returns ETIMEDOUT
+ if the system time equals or exceeds the time specified by abstime
+ before the condition variable is signaled or broadcast, _or_ if
+ the absolute time specified by abstime has already passed at the time
+ of the call.
+ For that reason, pthread_cond_timedwait will do the "timeoutting" job
+ even if its condition is always immediately signaled (case of a loaded
+ master).
+ */
+ error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime);
+ }
+ else
+ pthread_cond_wait(&data_cond, &data_lock);
+ DBUG_PRINT("info",("Got signal of master update or timed out"));
+ if (error == ETIMEDOUT || error == ETIME)
+ {
+ error= -1;
+ break;
+ }
+ error=0;
+ event_count++;
+ DBUG_PRINT("info",("Testing if killed or SQL thread not running"));
+ }
+
+err:
+ thd->exit_cond(msg);
+ DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \
+improper_arguments: %d timed_out: %d",
+ thd->killed_errno(),
+ (int) (init_abort_pos_wait != abort_pos_wait),
+ (int) slave_running,
+ (int) (error == -2),
+ (int) (error == -1)));
+ if (thd->killed || init_abort_pos_wait != abort_pos_wait ||
+ !slave_running)
+ {
+ error= -2;
+ }
+ DBUG_RETURN( error ? error : event_count );
+}
+
+
+void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
+ bool skip_lock)
+{
+ DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos");
+
+ if (!skip_lock)
+ pthread_mutex_lock(&data_lock);
+ inc_event_relay_log_pos();
+ group_relay_log_pos= event_relay_log_pos;
+ strmake(group_relay_log_name,event_relay_log_name,
+ sizeof(group_relay_log_name)-1);
+
+ notify_group_relay_log_name_update();
+
+ /*
+ If the slave does not support transactions and replicates a transaction,
+ users should not trust group_master_log_pos (which they can display with
+ SHOW SLAVE STATUS or read from relay-log.info), because to compute
+ group_master_log_pos the slave relies on log_pos stored in the master's
+ binlog, but if we are in a master's transaction these positions are always
+ the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does
+ not advance as it should on the non-transactional slave (it advances by
+ big leaps, whereas it should advance by small leaps).
+ */
+ /*
+ In 4.x we used the event's len to compute the positions here. This is
+ wrong if the event was 3.23/4.0 and has been converted to 5.0, because
+ then the event's len is not what is was in the master's binlog, so this
+ will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
+ replication: Exec_master_log_pos is wrong). Only way to solve this is to
+ have the original offset of the end of the event the relay log. This is
+ what we do in 5.0: log_pos has become "end_log_pos" (because the real use
+ of log_pos in 4.0 was to compute the end_log_pos; so better to store
+ end_log_pos instead of begin_log_pos.
+ If we had not done this fix here, the problem would also have appeared
+ when the slave and master are 5.0 but with different event length (for
+ example the slave is more recent than the master and features the event
+ UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
+ SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
+ value which would lead to badly broken replication.
+ Even the relay_log_pos will be corrupted in this case, because the len is
+ the relay log is not "val".
+ With the end_log_pos solution, we avoid computations involving lengthes.
+ */
+ DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
+ (long) log_pos, (long) group_master_log_pos));
+ if (log_pos) // 3.23 binlogs don't have log_posx
+ {
+ group_master_log_pos= log_pos;
+ }
+ pthread_cond_broadcast(&data_cond);
+ if (!skip_lock)
+ pthread_mutex_unlock(&data_lock);
+ DBUG_VOID_RETURN;
+}
+
+
+void st_relay_log_info::close_temporary_tables()
+{
+ TABLE *table,*next;
+ DBUG_ENTER("st_relay_log_info::close_temporary_tables");
+
+ for (table=save_temporary_tables ; table ; table=next)
+ {
+ next=table->next;
+ /*
+ Don't ask for disk deletion. For now, anyway they will be deleted when
+ slave restarts, but it is a better intention to not delete them.
+ */
+ DBUG_PRINT("info", ("table: 0x%lx", (long) table));
+ close_temporary(table, 1, 0);
+ }
+ save_temporary_tables= 0;
+ slave_open_temp_tables= 0;
+ DBUG_VOID_RETURN;
+}
+
+/*
+ purge_relay_logs()
+
+ NOTES
+ Assumes to have a run lock on rli and that no slave thread are running.
+*/
+
+int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
+ const char** errmsg)
+{
+ int error=0;
+ DBUG_ENTER("purge_relay_logs");
+
+ /*
+ Even if rli->inited==0, we still try to empty rli->master_log_* variables.
+ Indeed, rli->inited==0 does not imply that they already are empty.
+ It could be that slave's info initialization partly succeeded :
+ for example if relay-log.info existed but *relay-bin*.*
+ have been manually removed, init_relay_log_info reads the old
+ relay-log.info and fills rli->master_log_*, then init_relay_log_info
+ checks for the existence of the relay log, this fails and
+ init_relay_log_info leaves rli->inited to 0.
+ In that pathological case, rli->master_log_pos* will be properly reinited
+ at the next START SLAVE (as RESET SLAVE or CHANGE
+ MASTER, the callers of purge_relay_logs, will delete bogus *.info files
+ or replace them with correct files), however if the user does SHOW SLAVE
+ STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
+ In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
+ to display fine in any case.
+ */
+
+ rli->group_master_log_name[0]= 0;
+ rli->group_master_log_pos= 0;
+
+ if (!rli->inited)
+ {
+ DBUG_PRINT("info", ("rli->inited == 0"));
+ DBUG_RETURN(0);
+ }
+
+ DBUG_ASSERT(rli->slave_running == 0);
+ DBUG_ASSERT(rli->mi->slave_running == 0);
+
+ rli->slave_skip_counter=0;
+ pthread_mutex_lock(&rli->data_lock);
+
+ /*
+ we close the relay log fd possibly left open by the slave SQL thread,
+ to be able to delete it; the relay log fd possibly left open by the slave
+ I/O thread will be closed naturally in reset_logs() by the
+ close(LOG_CLOSE_TO_BE_OPENED) call
+ */
+ if (rli->cur_log_fd >= 0)
+ {
+ end_io_cache(&rli->cache_buf);
+ my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd= -1;
+ }
+
+ if (rli->relay_log.reset_logs(thd))
+ {
+ *errmsg = "Failed during log reset";
+ error=1;
+ goto err;
+ }
+ /* Save name of used relay log file */
+ strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
+ sizeof(rli->group_relay_log_name)-1);
+ strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
+ sizeof(rli->event_relay_log_name)-1);
+ rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
+ if (count_relay_log_space(rli))
+ {
+ *errmsg= "Error counting relay log space";
+ goto err;
+ }
+ if (!just_reset)
+ error= init_relay_log_pos(rli, rli->group_relay_log_name,
+ rli->group_relay_log_pos,
+ 0 /* do not need data lock */, errmsg, 0);
+
+err:
+#ifndef DBUG_OFF
+ char buf[22];
+#endif
+ DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf)));
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Check if condition stated in UNTIL clause of START SLAVE is reached.
+ SYNOPSYS
+ st_relay_log_info::is_until_satisfied()
+ DESCRIPTION
+ Checks if UNTIL condition is reached. Uses caching result of last
+ comparison of current log file name and target log file name. So cached
+ value should be invalidated if current log file name changes
+ (see st_relay_log_info::notify_... functions).
+
+ This caching is needed to avoid of expensive string comparisons and
+ strtol() conversions needed for log names comparison. We don't need to
+ compare them each time this function is called, we only need to do this
+ when current log name changes. If we have UNTIL_MASTER_POS condition we
+ need to do this only after Rotate_log_event::exec_event() (which is
+ rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS
+ condition then we should invalidate cached comarison value after
+ inc_group_relay_log_pos() which called for each group of events (so we
+ have some benefit if we have something like queries that use
+ autoincrement or if we have transactions).
+
+ Should be called ONLY if until_condition != UNTIL_NONE !
+ RETURN VALUE
+ true - condition met or error happened (condition seems to have
+ bad log file name)
+ false - condition not met
+*/
+
+bool st_relay_log_info::is_until_satisfied()
+{
+ const char *log_name;
+ ulonglong log_pos;
+ DBUG_ENTER("st_relay_log_info::is_until_satisfied");
+
+ DBUG_ASSERT(until_condition != UNTIL_NONE);
+
+ if (until_condition == UNTIL_MASTER_POS)
+ {
+ log_name= group_master_log_name;
+ log_pos= group_master_log_pos;
+ }
+ else
+ { /* until_condition == UNTIL_RELAY_POS */
+ log_name= group_relay_log_name;
+ log_pos= group_relay_log_pos;
+ }
+
+ if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN)
+ {
+ /*
+ We have no cached comparison results so we should compare log names
+ and cache result.
+ If we are after RESET SLAVE, and the SQL slave thread has not processed
+ any event yet, it could be that group_master_log_name is "". In that case,
+ just wait for more events (as there is no sensible comparison to do).
+ */
+
+ if (*log_name)
+ {
+ const char *basename= log_name + dirname_length(log_name);
+
+ const char *q= (const char*)(fn_ext(basename)+1);
+ if (strncmp(basename, until_log_name, (int)(q-basename)) == 0)
+ {
+ /* Now compare extensions. */
+ char *q_end;
+ ulong log_name_extension= strtoul(q, &q_end, 10);
+ if (log_name_extension < until_log_name_extension)
+ until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS;
+ else
+ until_log_names_cmp_result=
+ (log_name_extension > until_log_name_extension) ?
+ UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ;
+ }
+ else
+ {
+ /* Probably error so we aborting */
+ sql_print_error("Slave SQL thread is stopped because UNTIL "
+ "condition is bad.");
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else
+ DBUG_RETURN(until_log_pos == 0);
+ }
+
+ DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL &&
+ log_pos >= until_log_pos) ||
+ until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER));
+}
+
+
+void st_relay_log_info::cached_charset_invalidate()
+{
+ DBUG_ENTER("st_relay_log_info::cached_charset_invalidate");
+
+ /* Full of zeroes means uninitialized. */
+ bzero(cached_charset, sizeof(cached_charset));
+ DBUG_VOID_RETURN;
+}
+
+
+bool st_relay_log_info::cached_charset_compare(char *charset)
+{
+ DBUG_ENTER("st_relay_log_info::cached_charset_compare");
+
+ if (bcmp(cached_charset, charset, sizeof(cached_charset)))
+ {
+ memcpy(cached_charset, charset, sizeof(cached_charset));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+void st_relay_log_info::transaction_end(THD* thd)
+{
+ DBUG_ENTER("st_relay_log_info::transaction_end");
+
+ /*
+ Nothing to do here right now.
+ */
+
+ DBUG_VOID_RETURN;
+}
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+void st_relay_log_info::cleanup_context(THD *thd, bool error)
+{
+ DBUG_ENTER("st_relay_log_info::cleanup_context");
+
+ DBUG_ASSERT(sql_thd == thd);
+ /*
+ 1) Instances of Table_map_log_event, if ::exec_event() was called on them,
+ may have opened tables, which we cannot be sure have been closed (because
+ maybe the Rows_log_event have not been found or will not be, because slave
+ SQL thread is stopping, or relay log has a missing tail etc). So we close
+ all thread's tables. And so the table mappings have to be cancelled.
+ 2) Rows_log_event::exec_event() may even have started statements or
+ transactions on them, which we need to rollback in case of error.
+ 3) If finding a Format_description_log_event after a BEGIN, we also need
+ to rollback before continuing with the next events.
+ 4) so we need this "context cleanup" function.
+ */
+ if (error)
+ {
+ ha_autocommit_or_rollback(thd, 1); // if a "statement transaction"
+ end_trans(thd, ROLLBACK); // if a "real transaction"
+ }
+ m_table_map.clear_tables();
+ close_thread_tables(thd);
+ clear_tables_to_lock();
+ unsafe_to_stop_at= 0;
+ DBUG_VOID_RETURN;
+}
+#endif
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 392f12c2a71..d737055baf2 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -21,6 +21,7 @@
#include "rpl_tblmap.h"
+
/****************************************************************************
Replication SQL Thread
@@ -98,8 +99,8 @@ typedef struct st_relay_log_info
*/
pthread_cond_t start_cond, stop_cond, data_cond;
- /* parent master info structure */
- struct st_master_info *mi;
+ /* parent MASTER_INFO structure */
+ class MASTER_INFO *mi;
/*
Needed to deal properly with cur_log getting closed and re-opened with
@@ -164,6 +165,9 @@ typedef struct st_relay_log_info
time_t last_master_timestamp;
+ void clear_slave_error();
+ void clear_until_condition();
+
/*
Needed for problems when slave stops and we want to restart it
skipping one or more events in the master log that have caused
@@ -289,22 +293,6 @@ typedef struct st_relay_log_info
void cached_charset_invalidate();
bool cached_charset_compare(char *charset);
- /*
- To reload special tables when they are changes, we introduce a set
- of functions that will mark whenever special functions need to be
- called after modifying tables. Right now, the tables are either
- ACL tables or grants tables.
- */
- enum enum_reload_flag
- {
- RELOAD_NONE_F = 0UL,
- RELOAD_GRANT_F = (1UL << 0),
- RELOAD_ACCESS_F = (1UL << 1)
- };
-
- ulong m_reload_flags;
-
- void touching_table(char const* db, char const* table, ulong table_id);
void transaction_end(THD*);
void cleanup_context(THD *, bool);
@@ -322,4 +310,9 @@ typedef struct st_relay_log_info
time_t unsafe_to_stop_at;
} RELAY_LOG_INFO;
+
+// Defined in rpl_rli.cc
+int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
+
+
#endif /* RPL_RLI_H */
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
index a0272b23ee8..97f0066233c 100644
--- a/sql/rpl_tblmap.cc
+++ b/sql/rpl_tblmap.cc
@@ -50,17 +50,17 @@ table_mapping::~table_mapping()
st_table* table_mapping::get_table(ulong table_id)
{
DBUG_ENTER("table_mapping::get_table(ulong)");
- DBUG_PRINT("enter", ("table_id=%d", table_id));
+ DBUG_PRINT("enter", ("table_id: %lu", table_id));
entry *e= find_entry(table_id);
if (e)
{
- DBUG_PRINT("info", ("tid %d -> table %p (%s)",
- table_id, e->table,
+ DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)",
+ table_id, (long) e->table,
MAYBE_TABLE_NAME(e->table)));
DBUG_RETURN(e->table);
}
- DBUG_PRINT("info", ("tid %d is not mapped!", table_id));
+ DBUG_PRINT("info", ("tid %lu is not mapped!", table_id));
DBUG_RETURN(NULL);
}
@@ -93,9 +93,9 @@ int table_mapping::expand()
int table_mapping::set_table(ulong table_id, TABLE* table)
{
DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)");
- DBUG_PRINT("enter", ("table_id=%d, table=%p (%s)",
+ DBUG_PRINT("enter", ("table_id: %lu table: 0x%lx (%s)",
table_id,
- table, MAYBE_TABLE_NAME(table)));
+ (long) table, MAYBE_TABLE_NAME(table)));
entry *e= find_entry(table_id);
if (e == 0)
{
@@ -111,8 +111,8 @@ int table_mapping::set_table(ulong table_id, TABLE* table)
e->table= table;
my_hash_insert(&m_table_ids,(byte *)e);
- DBUG_PRINT("info", ("tid %d -> table %p (%s)",
- table_id, e->table,
+ DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)",
+ table_id, (long) e->table,
MAYBE_TABLE_NAME(e->table)));
DBUG_RETURN(0); // All OK
}
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index c80b6dc3f69..4bed1343e55 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -25,7 +25,7 @@ field_length_from_packed(enum_field_types const field_type,
switch (field_type) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- length= ~0UL;
+ length= ~(uint32) 0;
break;
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_TINY:
@@ -71,7 +71,7 @@ field_length_from_packed(enum_field_types const field_type,
break;
break;
case MYSQL_TYPE_BIT:
- length= ~0UL;
+ length= ~(uint32) 0;
break;
default:
/* This case should never be chosen */
@@ -85,7 +85,7 @@ field_length_from_packed(enum_field_types const field_type,
case MYSQL_TYPE_SET:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
- length= ~0UL; // NYI
+ length= ~(uint32) 0; // NYI
break;
case MYSQL_TYPE_TINY_BLOB:
@@ -93,7 +93,7 @@ field_length_from_packed(enum_field_types const field_type,
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
- length= ~0UL; // NYI
+ length= ~(uint32) 0; // NYI
break;
}
@@ -131,7 +131,8 @@ table_def::compatible_with(RELAY_LOG_INFO *rli, TABLE *table)
slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF,
"Table width mismatch - "
"received %u columns, %s.%s has %u columns",
- size(), tsh->db.str, tsh->table_name.str, tsh->fields);
+ (uint) size(), tsh->db.str, tsh->table_name.str,
+ tsh->fields);
}
for (uint col= 0 ; col < cols_to_check ; ++col)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 78916e50bc1..9f6499c7af1 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3930,7 +3930,7 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
DBUG_RETURN(TRUE);
}
- DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
+ DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
Item_result var_type= var->value->result_type();
diff --git a/sql/slave.cc b/sql/slave.cc
index 00d6d168fb8..4c5f0fc4764 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -31,13 +31,15 @@
#include "rpl_tblmap.h"
+int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
+
+
#define MAX_SLAVE_RETRY_PAUSE 5
bool use_slave_mask = 0;
MY_BITMAP slave_error_mask;
typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
-volatile bool slave_sql_running = 0, slave_io_running = 0;
char* slave_load_tmpdir = 0;
MASTER_INFO *active_mi= 0;
my_bool replicate_same_server_id;
@@ -59,7 +61,6 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli);
static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi);
static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli);
-static int count_relay_log_space(RELAY_LOG_INFO* rli);
static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type);
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
@@ -202,223 +203,6 @@ err:
/*
- Open the given relay log
-
- SYNOPSIS
- init_relay_log_pos()
- rli Relay information (will be initialized)
- log Name of relay log file to read from. NULL = First log
- pos Position in relay log file
- need_data_lock Set to 1 if this functions should do mutex locks
- errmsg Store pointer to error message here
- look_for_description_event
- 1 if we should look for such an event. We only need
- this when the SQL thread starts and opens an existing
- relay log and has to execute it (possibly from an
- offset >4); then we need to read the first event of
- the relay log to be able to parse the events we have
- to execute.
-
- DESCRIPTION
- - Close old open relay log files.
- - If we are using the same relay log as the running IO-thread, then set
- rli->cur_log to point to the same IO_CACHE entry.
- - If not, open the 'log' binary file.
-
- TODO
- - check proper initialization of group_master_log_name/group_master_log_pos
-
- RETURN VALUES
- 0 ok
- 1 error. errmsg is set to point to the error message
-*/
-
-int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
- ulonglong pos, bool need_data_lock,
- const char** errmsg,
- bool look_for_description_event)
-{
- DBUG_ENTER("init_relay_log_pos");
- DBUG_PRINT("info", ("pos=%lu", pos));
-
- *errmsg=0;
- pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
-
- if (need_data_lock)
- pthread_mutex_lock(&rli->data_lock);
-
- /*
- Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
- is, too, and init_slave() too; these 2 functions allocate a description
- event in init_relay_log_pos, which is not freed by the terminating SQL slave
- thread as that thread is not started by these functions. So we have to free
- the description_event here, in case, so that there is no memory leak in
- running, say, CHANGE MASTER.
- */
- delete rli->relay_log.description_event_for_exec;
- /*
- By default the relay log is in binlog format 3 (4.0).
- Even if format is 4, this will work enough to read the first event
- (Format_desc) (remember that format 4 is just lenghtened compared to format
- 3; format 3 is a prefix of format 4).
- */
- rli->relay_log.description_event_for_exec= new
- Format_description_log_event(3);
-
- pthread_mutex_lock(log_lock);
-
- /* Close log file and free buffers if it's already open */
- if (rli->cur_log_fd >= 0)
- {
- end_io_cache(&rli->cache_buf);
- my_close(rli->cur_log_fd, MYF(MY_WME));
- rli->cur_log_fd = -1;
- }
-
- rli->group_relay_log_pos = rli->event_relay_log_pos = pos;
-
- /*
- Test to see if the previous run was with the skip of purging
- If yes, we do not purge when we restart
- */
- if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1))
- {
- *errmsg="Could not find first log during relay log initialization";
- goto err;
- }
-
- if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1))
- {
- *errmsg="Could not find target log during relay log initialization";
- goto err;
- }
- strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
- sizeof(rli->group_relay_log_name)-1);
- strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
- sizeof(rli->event_relay_log_name)-1);
- if (rli->relay_log.is_active(rli->linfo.log_file_name))
- {
- /*
- The IO thread is using this log file.
- In this case, we will use the same IO_CACHE pointer to
- read data as the IO thread is using to write data.
- */
- my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0);
- if (check_binlog_magic(rli->cur_log,errmsg))
- goto err;
- rli->cur_log_old_open_count=rli->relay_log.get_open_count();
- }
- else
- {
- /*
- Open the relay log and set rli->cur_log to point at this one
- */
- if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
- rli->linfo.log_file_name,errmsg)) < 0)
- goto err;
- rli->cur_log = &rli->cache_buf;
- }
- /*
- In all cases, check_binlog_magic() has been called so we're at offset 4 for
- sure.
- */
- if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
- {
- Log_event* ev;
- while (look_for_description_event)
- {
- /*
- Read the possible Format_description_log_event; if position
- was 4, no need, it will be read naturally.
- */
- DBUG_PRINT("info",("looking for a Format_description_log_event"));
-
- if (my_b_tell(rli->cur_log) >= pos)
- break;
-
- /*
- Because of we have rli->data_lock and log_lock, we can safely read an
- event
- */
- if (!(ev=Log_event::read_log_event(rli->cur_log,0,
- rli->relay_log.description_event_for_exec)))
- {
- DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
- rli->cur_log->error));
- if (rli->cur_log->error) /* not EOF */
- {
- *errmsg= "I/O error reading event at position 4";
- goto err;
- }
- break;
- }
- else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
- {
- DBUG_PRINT("info",("found Format_description_log_event"));
- delete rli->relay_log.description_event_for_exec;
- rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
- /*
- As ev was returned by read_log_event, it has passed is_valid(), so
- my_malloc() in ctor worked, no need to check again.
- */
- /*
- Ok, we found a Format_description event. But it is not sure that this
- describes the whole relay log; indeed, one can have this sequence
- (starting from position 4):
- Format_desc (of slave)
- Rotate (of master)
- Format_desc (of master)
- So the Format_desc which really describes the rest of the relay log
- is the 3rd event (it can't be further than that, because we rotate
- the relay log when we queue a Rotate event from the master).
- But what describes the Rotate is the first Format_desc.
- So what we do is:
- go on searching for Format_description events, until you exceed the
- position (argument 'pos') or until you find another event than Rotate
- or Format_desc.
- */
- }
- else
- {
- DBUG_PRINT("info",("found event of another type=%d",
- ev->get_type_code()));
- look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
- delete ev;
- }
- }
- my_b_seek(rli->cur_log,(off_t)pos);
-#ifndef DBUG_OFF
- {
- char llbuf1[22], llbuf2[22];
- DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
- llstr(my_b_tell(rli->cur_log),llbuf1),
- llstr(rli->event_relay_log_pos,llbuf2)));
- }
-#endif
-
- }
-
-err:
- /*
- If we don't purge, we can't honour relay_log_space_limit ;
- silently discard it
- */
- if (!relay_log_purge)
- rli->log_space_limit= 0;
- pthread_cond_broadcast(&rli->data_cond);
-
- pthread_mutex_unlock(log_lock);
-
- if (need_data_lock)
- pthread_mutex_unlock(&rli->data_lock);
- if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
- *errmsg= "Invalid Format_description log event; could be out of memory";
-
- DBUG_RETURN ((*errmsg) ? 1 : 0);
-}
-
-
-/*
Init function to set up array for errors that should be skipped for slave
SYNOPSIS
@@ -461,174 +245,6 @@ void init_slave_skip_errors(const char* arg)
}
-void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
- bool skip_lock)
-{
- DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos");
-
- if (!skip_lock)
- pthread_mutex_lock(&data_lock);
- inc_event_relay_log_pos();
- group_relay_log_pos= event_relay_log_pos;
- strmake(group_relay_log_name,event_relay_log_name,
- sizeof(group_relay_log_name)-1);
-
- notify_group_relay_log_name_update();
-
- /*
- If the slave does not support transactions and replicates a transaction,
- users should not trust group_master_log_pos (which they can display with
- SHOW SLAVE STATUS or read from relay-log.info), because to compute
- group_master_log_pos the slave relies on log_pos stored in the master's
- binlog, but if we are in a master's transaction these positions are always
- the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does
- not advance as it should on the non-transactional slave (it advances by
- big leaps, whereas it should advance by small leaps).
- */
- /*
- In 4.x we used the event's len to compute the positions here. This is
- wrong if the event was 3.23/4.0 and has been converted to 5.0, because
- then the event's len is not what is was in the master's binlog, so this
- will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
- replication: Exec_master_log_pos is wrong). Only way to solve this is to
- have the original offset of the end of the event the relay log. This is
- what we do in 5.0: log_pos has become "end_log_pos" (because the real use
- of log_pos in 4.0 was to compute the end_log_pos; so better to store
- end_log_pos instead of begin_log_pos.
- If we had not done this fix here, the problem would also have appeared
- when the slave and master are 5.0 but with different event length (for
- example the slave is more recent than the master and features the event
- UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
- SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
- value which would lead to badly broken replication.
- Even the relay_log_pos will be corrupted in this case, because the len is
- the relay log is not "val".
- With the end_log_pos solution, we avoid computations involving lengthes.
- */
- DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
- (long) log_pos, (long) group_master_log_pos));
- if (log_pos) // 3.23 binlogs don't have log_posx
- {
- group_master_log_pos= log_pos;
- }
- pthread_cond_broadcast(&data_cond);
- if (!skip_lock)
- pthread_mutex_unlock(&data_lock);
- DBUG_VOID_RETURN;
-}
-
-
-void st_relay_log_info::close_temporary_tables()
-{
- TABLE *table,*next;
- DBUG_ENTER("st_relay_log_info::close_temporary_tables");
-
- for (table=save_temporary_tables ; table ; table=next)
- {
- next=table->next;
- /*
- Don't ask for disk deletion. For now, anyway they will be deleted when
- slave restarts, but it is a better intention to not delete them.
- */
- DBUG_PRINT("info", ("table: %p", table));
- close_temporary(table, 1, 0);
- }
- save_temporary_tables= 0;
- slave_open_temp_tables= 0;
- DBUG_VOID_RETURN;
-}
-
-/*
- purge_relay_logs()
-
- NOTES
- Assumes to have a run lock on rli and that no slave thread are running.
-*/
-
-int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
- const char** errmsg)
-{
- int error=0;
- DBUG_ENTER("purge_relay_logs");
-
- /*
- Even if rli->inited==0, we still try to empty rli->master_log_* variables.
- Indeed, rli->inited==0 does not imply that they already are empty.
- It could be that slave's info initialization partly succeeded :
- for example if relay-log.info existed but *relay-bin*.*
- have been manually removed, init_relay_log_info reads the old
- relay-log.info and fills rli->master_log_*, then init_relay_log_info
- checks for the existence of the relay log, this fails and
- init_relay_log_info leaves rli->inited to 0.
- In that pathological case, rli->master_log_pos* will be properly reinited
- at the next START SLAVE (as RESET SLAVE or CHANGE
- MASTER, the callers of purge_relay_logs, will delete bogus *.info files
- or replace them with correct files), however if the user does SHOW SLAVE
- STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
- In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
- to display fine in any case.
- */
-
- rli->group_master_log_name[0]= 0;
- rli->group_master_log_pos= 0;
-
- if (!rli->inited)
- {
- DBUG_PRINT("info", ("rli->inited == 0"));
- DBUG_RETURN(0);
- }
-
- DBUG_ASSERT(rli->slave_running == 0);
- DBUG_ASSERT(rli->mi->slave_running == 0);
-
- rli->slave_skip_counter=0;
- pthread_mutex_lock(&rli->data_lock);
-
- /*
- we close the relay log fd possibly left open by the slave SQL thread,
- to be able to delete it; the relay log fd possibly left open by the slave
- I/O thread will be closed naturally in reset_logs() by the
- close(LOG_CLOSE_TO_BE_OPENED) call
- */
- if (rli->cur_log_fd >= 0)
- {
- end_io_cache(&rli->cache_buf);
- my_close(rli->cur_log_fd, MYF(MY_WME));
- rli->cur_log_fd= -1;
- }
-
- if (rli->relay_log.reset_logs(thd))
- {
- *errmsg = "Failed during log reset";
- error=1;
- goto err;
- }
- /* Save name of used relay log file */
- strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
- sizeof(rli->group_relay_log_name)-1);
- strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
- sizeof(rli->event_relay_log_name)-1);
- rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
- if (count_relay_log_space(rli))
- {
- *errmsg= "Error counting relay log space";
- goto err;
- }
- if (!just_reset)
- error= init_relay_log_pos(rli, rli->group_relay_log_name,
- rli->group_relay_log_pos,
- 0 /* do not need data lock */, errmsg, 0);
-
-err:
-#ifndef DBUG_OFF
- char buf[22];
-#endif
- DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf)));
- pthread_mutex_unlock(&rli->data_lock);
- DBUG_RETURN(error);
-}
-
-
int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
{
DBUG_ENTER("terminate_slave_threads");
@@ -1023,7 +639,7 @@ const char *print_slave_db_safe(const char* db)
DBUG_RETURN((db ? db : ""));
}
-static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
const char *default_val)
{
uint length;
@@ -1054,7 +670,7 @@ static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
}
-static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
{
char buf[32];
DBUG_ENTER("init_intvar_from_file");
@@ -1456,261 +1072,6 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
}
-void end_master_info(MASTER_INFO* mi)
-{
- DBUG_ENTER("end_master_info");
-
- if (!mi->inited)
- DBUG_VOID_RETURN;
- end_relay_log_info(&mi->rli);
- if (mi->fd >= 0)
- {
- end_io_cache(&mi->file);
- (void)my_close(mi->fd, MYF(MY_WME));
- mi->fd = -1;
- }
- mi->inited = 0;
-
- DBUG_VOID_RETURN;
-}
-
-
-static int init_relay_log_info(RELAY_LOG_INFO* rli,
- const char* info_fname)
-{
- char fname[FN_REFLEN+128];
- int info_fd;
- const char* msg = 0;
- int error = 0;
- DBUG_ENTER("init_relay_log_info");
- DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage
-
- if (rli->inited) // Set if this function called
- DBUG_RETURN(0);
- fn_format(fname, info_fname, mysql_data_home, "", 4+32);
- pthread_mutex_lock(&rli->data_lock);
- info_fd = rli->info_fd;
- rli->cur_log_fd = -1;
- rli->slave_skip_counter=0;
- rli->abort_pos_wait=0;
- rli->log_space_limit= relay_log_space_limit;
- rli->log_space_total= 0;
- rli->tables_to_lock= 0;
- rli->tables_to_lock_count= 0;
-
- /*
- The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
- Note that the I/O thread flushes it to disk after writing every
- event, in flush_master_info(mi, 1).
- */
-
- /*
- For the maximum log size, we choose max_relay_log_size if it is
- non-zero, max_binlog_size otherwise. If later the user does SET
- GLOBAL on one of these variables, fix_max_binlog_size and
- fix_max_relay_log_size will reconsider the choice (for example
- if the user changes max_relay_log_size to zero, we have to
- switch to using max_binlog_size for the relay log) and update
- rli->relay_log.max_size (and mysql_bin_log.max_size).
- */
- {
- char buf[FN_REFLEN];
- const char *ln;
- static bool name_warning_sent= 0;
- ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
- 1, buf);
- /* We send the warning only at startup, not after every RESET SLAVE */
- if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent)
- {
- /*
- User didn't give us info to name the relay log index file.
- Picking `hostname`-relay-bin.index like we do, causes replication to
- fail if this slave's hostname is changed later. So, we would like to
- instead require a name. But as we don't want to break many existing
- setups, we only give warning, not error.
- */
- sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
- " so replication "
- "may break when this MySQL server acts as a "
- "slave and has his hostname changed!! Please "
- "use '--relay-log=%s' to avoid this problem.", ln);
- name_warning_sent= 1;
- }
- /*
- note, that if open() fails, we'll still have index file open
- but a destructor will take care of that
- */
- if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
- rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
- (max_relay_log_size ? max_relay_log_size :
- max_binlog_size), 1))
- {
- pthread_mutex_unlock(&rli->data_lock);
- sql_print_error("Failed in open_log() called from init_relay_log_info()");
- DBUG_RETURN(1);
- }
- }
-
- /* if file does not exist */
- if (access(fname,F_OK))
- {
- /*
- If someone removed the file from underneath our feet, just close
- the old descriptor and re-create the old file
- */
- if (info_fd >= 0)
- my_close(info_fd, MYF(MY_WME));
- if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
- {
- sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
- msg= current_thd->net.last_error;
- goto err;
- }
- if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
- MYF(MY_WME)))
- {
- sql_print_error("Failed to create a cache on relay log info file '%s'",
- fname);
- msg= current_thd->net.last_error;
- goto err;
- }
-
- /* Init relay log with first entry in the relay index file */
- if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
- &msg, 0))
- {
- sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
- goto err;
- }
- rli->group_master_log_name[0]= 0;
- rli->group_master_log_pos= 0;
- rli->info_fd= info_fd;
- }
- else // file exists
- {
- if (info_fd >= 0)
- reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
- else
- {
- int error=0;
- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
- {
- sql_print_error("\
-Failed to open the existing relay log info file '%s' (errno %d)",
- fname, my_errno);
- error= 1;
- }
- else if (init_io_cache(&rli->info_file, info_fd,
- IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
- {
- sql_print_error("Failed to create a cache on relay log info file '%s'",
- fname);
- error= 1;
- }
- if (error)
- {
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
- rli->info_fd= -1;
- rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
- pthread_mutex_unlock(&rli->data_lock);
- DBUG_RETURN(1);
- }
- }
-
- rli->info_fd = info_fd;
- int relay_log_pos, master_log_pos;
- if (init_strvar_from_file(rli->group_relay_log_name,
- sizeof(rli->group_relay_log_name),
- &rli->info_file, "") ||
- init_intvar_from_file(&relay_log_pos,
- &rli->info_file, BIN_LOG_HEADER_SIZE) ||
- init_strvar_from_file(rli->group_master_log_name,
- sizeof(rli->group_master_log_name),
- &rli->info_file, "") ||
- init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
- {
- msg="Error reading slave log configuration";
- goto err;
- }
- strmake(rli->event_relay_log_name,rli->group_relay_log_name,
- sizeof(rli->event_relay_log_name)-1);
- rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
- rli->group_master_log_pos= master_log_pos;
-
- if (init_relay_log_pos(rli,
- rli->group_relay_log_name,
- rli->group_relay_log_pos,
- 0 /* no data lock*/,
- &msg, 0))
- {
- char llbuf[22];
- sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
- rli->group_relay_log_name,
- llstr(rli->group_relay_log_pos, llbuf));
- goto err;
- }
- }
-
-#ifndef DBUG_OFF
- {
- char llbuf1[22], llbuf2[22];
- DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
- llstr(my_b_tell(rli->cur_log),llbuf1),
- llstr(rli->event_relay_log_pos,llbuf2)));
- DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
- DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
- }
-#endif
-
- /*
- Now change the cache from READ to WRITE - must do this
- before flush_relay_log_info
- */
- reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
- if ((error= flush_relay_log_info(rli)))
- sql_print_error("Failed to flush relay log info file");
- if (count_relay_log_space(rli))
- {
- msg="Error counting relay log space";
- goto err;
- }
- rli->inited= 1;
- pthread_mutex_unlock(&rli->data_lock);
- DBUG_RETURN(error);
-
-err:
- sql_print_error(msg);
- end_io_cache(&rli->info_file);
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
- rli->info_fd= -1;
- rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
- pthread_mutex_unlock(&rli->data_lock);
- DBUG_RETURN(1);
-}
-
-
-static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
-{
- MY_STAT s;
- DBUG_ENTER("add_relay_log");
- if (!my_stat(linfo->log_file_name,&s,MYF(0)))
- {
- sql_print_error("log %s listed in the index, but failed to stat",
- linfo->log_file_name);
- DBUG_RETURN(1);
- }
- rli->log_space_total += s.st_size;
-#ifndef DBUG_OFF
- char buf[22];
- DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf)));
-#endif
- DBUG_RETURN(0);
-}
-
-
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
{
bool slave_killed=0;
@@ -1733,31 +1094,6 @@ Waiting for the slave SQL thread to free enough relay log space");
}
-static int count_relay_log_space(RELAY_LOG_INFO* rli)
-{
- LOG_INFO linfo;
- DBUG_ENTER("count_relay_log_space");
- rli->log_space_total= 0;
- if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
- {
- sql_print_error("Could not find first log while counting relay log space");
- DBUG_RETURN(1);
- }
- do
- {
- if (add_relay_log(rli,&linfo))
- DBUG_RETURN(1);
- } while (!rli->relay_log.find_next_log(&linfo, 1));
- /*
- As we have counted everything, including what may have written in a
- preceding write, we must reset bytes_written, or we may count some space
- twice.
- */
- rli->relay_log.reset_bytes_written();
- DBUG_RETURN(0);
-}
-
-
/*
Builds a Rotate from the ignored events' info and writes it to relay log.
@@ -1811,284 +1147,6 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi)
}
-void init_master_info_with_options(MASTER_INFO* mi)
-{
- DBUG_ENTER("init_master_info_with_options");
-
- mi->master_log_name[0] = 0;
- mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number
-
- if (master_host)
- strmake(mi->host, master_host, sizeof(mi->host) - 1);
- if (master_user)
- strmake(mi->user, master_user, sizeof(mi->user) - 1);
- if (master_password)
- strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
- mi->port = master_port;
- mi->connect_retry = master_connect_retry;
-
- mi->ssl= master_ssl;
- if (master_ssl_ca)
- strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1);
- if (master_ssl_capath)
- strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1);
- if (master_ssl_cert)
- strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1);
- if (master_ssl_cipher)
- strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1);
- if (master_ssl_key)
- strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1);
- DBUG_VOID_RETURN;
-}
-
-void clear_slave_error(RELAY_LOG_INFO* rli)
-{
- DBUG_ENTER("clear_slave_error");
-
- /* Clear the errors displayed by SHOW SLAVE STATUS */
- rli->last_slave_error[0]= 0;
- rli->last_slave_errno= 0;
- DBUG_VOID_RETURN;
-}
-
-/*
- Reset UNTIL condition for RELAY_LOG_INFO
- SYNOPSYS
- clear_until_condition()
- rli - RELAY_LOG_INFO structure where UNTIL condition should be reset
- */
-void clear_until_condition(RELAY_LOG_INFO* rli)
-{
- DBUG_ENTER("clear_until_condition");
-
- rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE;
- rli->until_log_name[0]= 0;
- rli->until_log_pos= 0;
- DBUG_VOID_RETURN;
-}
-
-
-#define LINES_IN_MASTER_INFO_WITH_SSL 14
-
-
-int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
- const char* slave_info_fname,
- bool abort_if_no_master_info_file,
- int thread_mask)
-{
- int fd,error;
- char fname[FN_REFLEN+128];
- DBUG_ENTER("init_master_info");
-
- if (mi->inited)
- {
- /*
- We have to reset read position of relay-log-bin as we may have
- already been reading from 'hotlog' when the slave was stopped
- last time. If this case pos_in_file would be set and we would
- get a crash when trying to read the signature for the binary
- relay log.
-
- We only rewind the read position if we are starting the SQL
- thread. The handle_slave_sql thread assumes that the read
- position is at the beginning of the file, and will read the
- "signature" and then fast-forward to the last position read.
- */
- if (thread_mask & SLAVE_SQL)
- {
- my_b_seek(mi->rli.cur_log, (my_off_t) 0);
- }
- DBUG_RETURN(0);
- }
-
- mi->mysql=0;
- mi->file_id=1;
- fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
-
- /*
- We need a mutex while we are changing master info parameters to
- keep other threads from reading bogus info
- */
-
- pthread_mutex_lock(&mi->data_lock);
- fd = mi->fd;
-
- /* does master.info exist ? */
-
- if (access(fname,F_OK))
- {
- if (abort_if_no_master_info_file)
- {
- pthread_mutex_unlock(&mi->data_lock);
- DBUG_RETURN(0);
- }
- /*
- if someone removed the file from underneath our feet, just close
- the old descriptor and re-create the old file
- */
- if (fd >= 0)
- my_close(fd, MYF(MY_WME));
- if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
- {
- sql_print_error("Failed to create a new master info file (\
-file '%s', errno %d)", fname, my_errno);
- goto err;
- }
- if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
- MYF(MY_WME)))
- {
- sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
- goto err;
- }
-
- mi->fd = fd;
- init_master_info_with_options(mi);
-
- }
- else // file exists
- {
- if (fd >= 0)
- reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
- else
- {
- if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
- {
- sql_print_error("Failed to open the existing master info file (\
-file '%s', errno %d)", fname, my_errno);
- goto err;
- }
- if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
- 0, MYF(MY_WME)))
- {
- sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
- goto err;
- }
- }
-
- mi->fd = fd;
- int port, connect_retry, master_log_pos, ssl= 0, lines;
- char *first_non_digit;
-
- /*
- Starting from 4.1.x master.info has new format. Now its
- first line contains number of lines in file. By reading this
- number we will be always distinguish to which version our
- master.info corresponds to. We can't simply count lines in
- file since versions before 4.1.x could generate files with more
- lines than needed.
- If first line doesn't contain a number or contain number less than
- 14 then such file is treated like file from pre 4.1.1 version.
- There is no ambiguity when reading an old master.info, as before
- 4.1.1, the first line contained the binlog's name, which is either
- empty or has an extension (contains a '.'), so can't be confused
- with an integer.
-
- So we're just reading first line and trying to figure which version
- is this.
- */
-
- /*
- The first row is temporarily stored in mi->master_log_name,
- if it is line count and not binlog name (new format) it will be
- overwritten by the second row later.
- */
- if (init_strvar_from_file(mi->master_log_name,
- sizeof(mi->master_log_name), &mi->file,
- ""))
- goto errwithmsg;
-
- lines= strtoul(mi->master_log_name, &first_non_digit, 10);
-
- if (mi->master_log_name[0]!='\0' &&
- *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
- { // Seems to be new format
- if (init_strvar_from_file(mi->master_log_name,
- sizeof(mi->master_log_name), &mi->file, ""))
- goto errwithmsg;
- }
- else
- lines= 7;
-
- if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
- init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
- master_host) ||
- init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
- master_user) ||
- init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
- &mi->file, master_password) ||
- init_intvar_from_file(&port, &mi->file, master_port) ||
- init_intvar_from_file(&connect_retry, &mi->file,
- master_connect_retry))
- goto errwithmsg;
-
- /*
- If file has ssl part use it even if we have server without
- SSL support. But these option will be ignored later when
- slave will try connect to master, so in this case warning
- is printed.
- */
- if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
- (init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
- init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
- &mi->file, master_ssl_ca) ||
- init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
- &mi->file, master_ssl_capath) ||
- init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
- &mi->file, master_ssl_cert) ||
- init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
- &mi->file, master_ssl_cipher) ||
- init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
- &mi->file, master_ssl_key)))
- goto errwithmsg;
-#ifndef HAVE_OPENSSL
- if (ssl)
- sql_print_warning("SSL information in the master info file "
- "('%s') are ignored because this MySQL slave was compiled "
- "without SSL support.", fname);
-#endif /* HAVE_OPENSSL */
-
- /*
- This has to be handled here as init_intvar_from_file can't handle
- my_off_t types
- */
- mi->master_log_pos= (my_off_t) master_log_pos;
- mi->port= (uint) port;
- mi->connect_retry= (uint) connect_retry;
- mi->ssl= (my_bool) ssl;
- }
- DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
- mi->master_log_name,
- (ulong) mi->master_log_pos));
-
- mi->rli.mi = mi;
- if (init_relay_log_info(&mi->rli, slave_info_fname))
- goto err;
-
- mi->inited = 1;
- // now change cache READ -> WRITE - must do this before flush_master_info
- reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
- if ((error=test(flush_master_info(mi, 1))))
- sql_print_error("Failed to flush master info file");
- pthread_mutex_unlock(&mi->data_lock);
- DBUG_RETURN(error);
-
-errwithmsg:
- sql_print_error("Error reading master configuration");
-
-err:
- if (fd >= 0)
- {
- my_close(fd, MYF(0));
- end_io_cache(&mi->file);
- }
- mi->fd= -1;
- pthread_mutex_unlock(&mi->data_lock);
- DBUG_RETURN(1);
-}
-
-
int register_slave_on_master(MYSQL* mysql)
{
char buf[1024], *pos= buf;
@@ -2307,313 +1365,6 @@ bool show_master_info(THD* thd, MASTER_INFO* mi)
DBUG_RETURN(FALSE);
}
-/*
- RETURN
- 2 - flush relay log failed
- 1 - flush master info failed
- 0 - all ok
-*/
-int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
-{
- IO_CACHE* file = &mi->file;
- char lbuf[22];
- DBUG_ENTER("flush_master_info");
- DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
-
- /*
- Flush the relay log to disk. If we don't do it, then the relay log while
- have some part (its last kilobytes) in memory only, so if the slave server
- dies now, with, say, from master's position 100 to 150 in memory only (not
- on disk), and with position 150 in master.info, then when the slave
- restarts, the I/O thread will fetch binlogs from 150, so in the relay log
- we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
- SQL thread will jump from 100 to 150, and replication will silently break.
-
- When we come to this place in code, relay log may or not be initialized;
- the caller is responsible for setting 'flush_relay_log_cache' accordingly.
- */
- if (flush_relay_log_cache &&
- flush_io_cache(mi->rli.relay_log.get_log_file()))
- DBUG_RETURN(2);
-
- /*
- We flushed the relay log BEFORE the master.info file, because if we crash
- now, we will get a duplicate event in the relay log at restart. If we
- flushed in the other order, we would get a hole in the relay log.
- And duplicate is better than hole (with a duplicate, in later versions we
- can add detection and scrap one event; with a hole there's nothing we can
- do).
- */
-
- /*
- In certain cases this code may create master.info files that seems
- corrupted, because of extra lines filled with garbage in the end
- file (this happens if new contents take less space than previous
- contents of file). But because of number of lines in the first line
- of file we don't care about this garbage.
- */
-
- my_b_seek(file, 0L);
- my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n",
- LINES_IN_MASTER_INFO_WITH_SSL,
- mi->master_log_name, llstr(mi->master_log_pos, lbuf),
- mi->host, mi->user,
- mi->password, mi->port, mi->connect_retry,
- (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
- mi->ssl_cipher, mi->ssl_key);
- DBUG_RETURN(-flush_io_cache(file));
-}
-
-
-st_relay_log_info::st_relay_log_info()
- :no_storage(FALSE), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
- cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0),
- ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0),
- abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0),
- inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
- until_log_pos(0), retried_trans(0),
- tables_to_lock(0), tables_to_lock_count(0),
- m_reload_flags(RELOAD_NONE_F),
- unsafe_to_stop_at(0)
-{
- DBUG_ENTER("st_relay_log_info::st_relay_log_info");
-
- group_relay_log_name[0]= event_relay_log_name[0]=
- group_master_log_name[0]= 0;
- last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0;
- bzero((char*) &info_file, sizeof(info_file));
- bzero((char*) &cache_buf, sizeof(cache_buf));
- cached_charset_invalidate();
- pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&data_cond, NULL);
- pthread_cond_init(&start_cond, NULL);
- pthread_cond_init(&stop_cond, NULL);
- pthread_cond_init(&log_space_cond, NULL);
- relay_log.init_pthread_objects();
- DBUG_VOID_RETURN;
-}
-
-
-st_relay_log_info::~st_relay_log_info()
-{
- DBUG_ENTER("st_relay_log_info::~st_relay_log_info");
-
- pthread_mutex_destroy(&run_lock);
- pthread_mutex_destroy(&data_lock);
- pthread_mutex_destroy(&log_space_lock);
- pthread_cond_destroy(&data_cond);
- pthread_cond_destroy(&start_cond);
- pthread_cond_destroy(&stop_cond);
- pthread_cond_destroy(&log_space_cond);
- relay_log.cleanup();
- DBUG_VOID_RETURN;
-}
-
-/*
- Waits until the SQL thread reaches (has executed up to) the
- log/position or timed out.
-
- SYNOPSIS
- wait_for_pos()
- thd client thread that sent SELECT MASTER_POS_WAIT
- log_name log name to wait for
- log_pos position to wait for
- timeout timeout in seconds before giving up waiting
-
- NOTES
- timeout is longlong whereas it should be ulong ; but this is
- to catch if the user submitted a negative timeout.
-
- RETURN VALUES
- -2 improper arguments (log_pos<0)
- or slave not running, or master info changed
- during the function's execution,
- or client thread killed. -2 is translated to NULL by caller
- -1 timed out
- >=0 number of log events the function had to wait
- before reaching the desired log/position
- */
-
-int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
- longlong log_pos,
- longlong timeout)
-{
- int event_count = 0;
- ulong init_abort_pos_wait;
- int error=0;
- struct timespec abstime; // for timeout checking
- const char *msg;
- DBUG_ENTER("st_relay_log_info::wait_for_pos");
-
- if (!inited)
- DBUG_RETURN(-1);
-
- DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu",
- log_name->c_ptr(), (ulong) log_pos, (ulong) timeout));
-
- set_timespec(abstime,timeout);
- pthread_mutex_lock(&data_lock);
- msg= thd->enter_cond(&data_cond, &data_lock,
- "Waiting for the slave SQL thread to "
- "advance position");
- /*
- This function will abort when it notices that some CHANGE MASTER or
- RESET MASTER has changed the master info.
- To catch this, these commands modify abort_pos_wait ; We just monitor
- abort_pos_wait and see if it has changed.
- Why do we have this mechanism instead of simply monitoring slave_running
- in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that
- the SQL thread be stopped?
- This is becasue if someones does:
- STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE;
- the change may happen very quickly and we may not notice that
- slave_running briefly switches between 1/0/1.
- */
- init_abort_pos_wait= abort_pos_wait;
-
- /*
- We'll need to
- handle all possible log names comparisons (e.g. 999 vs 1000).
- We use ulong for string->number conversion ; this is no
- stronger limitation than in find_uniq_filename in sql/log.cc
- */
- ulong log_name_extension;
- char log_name_tmp[FN_REFLEN]; //make a char[] from String
-
- strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1));
-
- char *p= fn_ext(log_name_tmp);
- char *p_end;
- if (!*p || log_pos<0)
- {
- error= -2; //means improper arguments
- goto err;
- }
- // Convert 0-3 to 4
- log_pos= max(log_pos, BIN_LOG_HEADER_SIZE);
- /* p points to '.' */
- log_name_extension= strtoul(++p, &p_end, 10);
- /*
- p_end points to the first invalid character.
- If it equals to p, no digits were found, error.
- If it contains '\0' it means conversion went ok.
- */
- if (p_end==p || *p_end)
- {
- error= -2;
- goto err;
- }
-
- /* The "compare and wait" main loop */
- while (!thd->killed &&
- init_abort_pos_wait == abort_pos_wait &&
- slave_running)
- {
- bool pos_reached;
- int cmp_result= 0;
-
- DBUG_PRINT("info",
- ("init_abort_pos_wait: %ld abort_pos_wait: %ld",
- init_abort_pos_wait, abort_pos_wait));
- DBUG_PRINT("info",("group_master_log_name: '%s' pos: %lu",
- group_master_log_name, (ulong) group_master_log_pos));
-
- /*
- group_master_log_name can be "", if we are just after a fresh
- replication start or after a CHANGE MASTER TO MASTER_HOST/PORT
- (before we have executed one Rotate event from the master) or
- (rare) if the user is doing a weird slave setup (see next
- paragraph). If group_master_log_name is "", we assume we don't
- have enough info to do the comparison yet, so we just wait until
- more data. In this case master_log_pos is always 0 except if
- somebody (wrongly) sets this slave to be a slave of itself
- without using --replicate-same-server-id (an unsupported
- configuration which does nothing), then group_master_log_pos
- will grow and group_master_log_name will stay "".
- */
- if (*group_master_log_name)
- {
- char *basename= (group_master_log_name +
- dirname_length(group_master_log_name));
- /*
- First compare the parts before the extension.
- Find the dot in the master's log basename,
- and protect against user's input error :
- if the names do not match up to '.' included, return error
- */
- char *q= (char*)(fn_ext(basename)+1);
- if (strncmp(basename, log_name_tmp, (int)(q-basename)))
- {
- error= -2;
- break;
- }
- // Now compare extensions.
- char *q_end;
- ulong group_master_log_name_extension= strtoul(q, &q_end, 10);
- if (group_master_log_name_extension < log_name_extension)
- cmp_result= -1 ;
- else
- cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ;
-
- pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) ||
- cmp_result > 0);
- if (pos_reached || thd->killed)
- break;
- }
-
- //wait for master update, with optional timeout.
-
- DBUG_PRINT("info",("Waiting for master update"));
- /*
- We are going to pthread_cond_(timed)wait(); if the SQL thread stops it
- will wake us up.
- */
- if (timeout > 0)
- {
- /*
- Note that pthread_cond_timedwait checks for the timeout
- before for the condition ; i.e. it returns ETIMEDOUT
- if the system time equals or exceeds the time specified by abstime
- before the condition variable is signaled or broadcast, _or_ if
- the absolute time specified by abstime has already passed at the time
- of the call.
- For that reason, pthread_cond_timedwait will do the "timeoutting" job
- even if its condition is always immediately signaled (case of a loaded
- master).
- */
- error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime);
- }
- else
- pthread_cond_wait(&data_cond, &data_lock);
- DBUG_PRINT("info",("Got signal of master update or timed out"));
- if (error == ETIMEDOUT || error == ETIME)
- {
- error= -1;
- break;
- }
- error=0;
- event_count++;
- DBUG_PRINT("info",("Testing if killed or SQL thread not running"));
- }
-
-err:
- thd->exit_cond(msg);
- DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \
-improper_arguments: %d timed_out: %d",
- thd->killed_errno(),
- (int) (init_abort_pos_wait != abort_pos_wait),
- (int) slave_running,
- (int) (error == -2),
- (int) (error == -1)));
- if (thd->killed || init_abort_pos_wait != abort_pos_wait ||
- !slave_running)
- {
- error= -2;
- }
- DBUG_RETURN( error ? error : event_count );
-}
void set_slave_thread_options(THD* thd)
{
@@ -2663,6 +1414,13 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
thd->security_ctx->skip_grants();
my_net_init(&thd->net, 0);
+/*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
+ slave threads, since a replication event can become this much larger
+ than the corresponding packet (query) sent from client to master.
+*/
+ thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
thd->net.read_timeout = slave_net_timeout;
thd->slave_thread = 1;
set_slave_thread_options(thd);
@@ -2851,7 +1609,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
DBUG_RETURN(packet_error);
}
- DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
+ DBUG_PRINT("exit", ("len: %lu net->read_pos[4]: %d",
len, mysql->net.read_pos[4]));
DBUG_RETURN(len - 1);
}
@@ -2872,119 +1630,6 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
}
}
-/*
- Check if condition stated in UNTIL clause of START SLAVE is reached.
- SYNOPSYS
- st_relay_log_info::is_until_satisfied()
- DESCRIPTION
- Checks if UNTIL condition is reached. Uses caching result of last
- comparison of current log file name and target log file name. So cached
- value should be invalidated if current log file name changes
- (see st_relay_log_info::notify_... functions).
-
- This caching is needed to avoid of expensive string comparisons and
- strtol() conversions needed for log names comparison. We don't need to
- compare them each time this function is called, we only need to do this
- when current log name changes. If we have UNTIL_MASTER_POS condition we
- need to do this only after Rotate_log_event::exec_event() (which is
- rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS
- condition then we should invalidate cached comarison value after
- inc_group_relay_log_pos() which called for each group of events (so we
- have some benefit if we have something like queries that use
- autoincrement or if we have transactions).
-
- Should be called ONLY if until_condition != UNTIL_NONE !
- RETURN VALUE
- true - condition met or error happened (condition seems to have
- bad log file name)
- false - condition not met
-*/
-
-bool st_relay_log_info::is_until_satisfied()
-{
- const char *log_name;
- ulonglong log_pos;
- DBUG_ENTER("st_relay_log_info::is_until_satisfied");
-
- DBUG_ASSERT(until_condition != UNTIL_NONE);
-
- if (until_condition == UNTIL_MASTER_POS)
- {
- log_name= group_master_log_name;
- log_pos= group_master_log_pos;
- }
- else
- { /* until_condition == UNTIL_RELAY_POS */
- log_name= group_relay_log_name;
- log_pos= group_relay_log_pos;
- }
-
- if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN)
- {
- /*
- We have no cached comparison results so we should compare log names
- and cache result.
- If we are after RESET SLAVE, and the SQL slave thread has not processed
- any event yet, it could be that group_master_log_name is "". In that case,
- just wait for more events (as there is no sensible comparison to do).
- */
-
- if (*log_name)
- {
- const char *basename= log_name + dirname_length(log_name);
-
- const char *q= (const char*)(fn_ext(basename)+1);
- if (strncmp(basename, until_log_name, (int)(q-basename)) == 0)
- {
- /* Now compare extensions. */
- char *q_end;
- ulong log_name_extension= strtoul(q, &q_end, 10);
- if (log_name_extension < until_log_name_extension)
- until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS;
- else
- until_log_names_cmp_result=
- (log_name_extension > until_log_name_extension) ?
- UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ;
- }
- else
- {
- /* Probably error so we aborting */
- sql_print_error("Slave SQL thread is stopped because UNTIL "
- "condition is bad.");
- DBUG_RETURN(TRUE);
- }
- }
- else
- DBUG_RETURN(until_log_pos == 0);
- }
-
- DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL &&
- log_pos >= until_log_pos) ||
- until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER));
-}
-
-
-void st_relay_log_info::cached_charset_invalidate()
-{
- DBUG_ENTER("st_relay_log_info::cached_charset_invalidate");
-
- /* Full of zeroes means uninitialized. */
- bzero(cached_charset, sizeof(cached_charset));
- DBUG_VOID_RETURN;
-}
-
-
-bool st_relay_log_info::cached_charset_compare(char *charset)
-{
- DBUG_ENTER("st_relay_log_info::cached_charset_compare");
-
- if (bcmp(cached_charset, charset, sizeof(cached_charset)))
- {
- memcpy(cached_charset, charset, sizeof(cached_charset));
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
-}
/*
Check if the current error is of temporary nature of not.
@@ -3155,7 +1800,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
ev->when = time(NULL);
ev->thd = thd; // because up to this point, ev->thd == 0
exec_res = ev->exec_event(rli);
- DBUG_PRINT("info", ("exec_event result = %d", exec_res));
+ DBUG_PRINT("info", ("exec_event result: %d", exec_res));
DBUG_ASSERT(rli->sql_thd==thd);
/*
Format_description_log_event should not be deleted because it will be
@@ -3176,6 +1821,8 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
We were in a transaction which has been rolled back because of a
temporary error;
let's seek back to BEGIN log event and retry it all again.
+ Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
+ there is no rollback since 5.0.13 (ref: manual).
We have to not only seek but also
a) init_master_info(), to seek back to hot relay log's start for later
(for when we will come back to this hot log after re-processing the
@@ -3303,11 +1950,19 @@ pthread_handler_t handle_slave_io(void *arg)
thd->proc_info = "Connecting to master";
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, mi))
- sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\
- replication started in log '%s' at position %s", mi->user,
- mi->host, mi->port,
- IO_RPL_LOG_NAME,
- llstr(mi->master_log_pos,llbuff));
+ {
+ sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',"
+ "replication started in log '%s' at position %s",
+ mi->user, mi->host, mi->port,
+ IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
+ thread, since a replication event can become this much larger than
+ the corresponding packet (query) sent from client to master.
+ */
+ mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
+ }
else
{
sql_print_information("Slave I/O thread killed while connecting to master");
@@ -3632,7 +2287,7 @@ pthread_handler_t handle_slave_sql(void *arg)
now.
But the master timestamp is reset by RESET SLAVE & CHANGE MASTER.
*/
- clear_slave_error(rli);
+ rli->clear_slave_error();
//tell the I/O thread to take relay_log_space_limit into account from now on
pthread_mutex_lock(&rli->log_space_lock);
@@ -3949,7 +2604,7 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
/* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
- DBUG_PRINT("info", ("master_log_pos: '%s' %d",
+ DBUG_PRINT("info", ("master_log_pos: '%s' %lu",
mi->master_log_name, (ulong) mi->master_log_pos));
#ifndef DBUG_OFF
/*
@@ -4066,7 +2721,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
int error = process_io_create_file(mi,(Create_file_log_event*)ev);
delete ev;
mi->master_log_pos += inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
my_free((char*)tmp_buf, MYF(0));
DBUG_RETURN(error);
@@ -4093,7 +2748,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
}
delete ev;
mi->master_log_pos+= inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(0);
}
@@ -4149,7 +2804,7 @@ static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf,
delete ev;
mi->master_log_pos+= inc_pos;
err:
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(0);
}
@@ -4322,7 +2977,8 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
rli->ign_master_log_pos_end= mi->master_log_pos;
}
rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
- DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu, event originating from the same server, ignored",
+ (ulong) mi->master_log_pos));
}
else
{
@@ -4330,7 +2986,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
else
@@ -4451,11 +3107,11 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
{
last_errno=mysql_errno(mysql);
suppress_warnings= 0;
- sql_print_error("Slave I/O thread: error %s to master \
-'%s@%s:%d': \
+ sql_print_error("Slave I/O thread: error %s to master "
+ "'%s@%s:%d': \
Error: '%s' errno: %d retry-time: %d retries: %lu",
(reconnect ? "reconnecting" : "connecting"),
- mi->user,mi->host,mi->port,
+ mi->user, mi->host, mi->port,
mysql_error(mysql), last_errno,
mi->connect_retry,
master_retry_count);
@@ -4990,121 +3646,6 @@ end:
DBUG_VOID_RETURN;
}
-/*
- Some system tables needed to be re-read by the MySQL server after it has
- updated them; in statement-based replication, the GRANT and other commands
- are sent verbatim to the slave which then reloads; in row-based replication,
- changes to these tables are done through ordinary Rows binlog events, so
- master must add some flag for the slave to know it has to reload the tables.
-*/
-struct st_reload_entry
-{
- char const *table;
- st_relay_log_info::enum_reload_flag flag;
-};
-
-/*
- Sorted array of table names, please keep it sorted since we are
- using bsearch() on it below.
- */
-static st_reload_entry s_mysql_tables[] =
-{
- { "columns_priv", st_relay_log_info::RELOAD_GRANT_F },
- { "db", st_relay_log_info::RELOAD_ACCESS_F },
- { "host", st_relay_log_info::RELOAD_ACCESS_F },
- { "procs_priv", st_relay_log_info::RELOAD_GRANT_F },
- { "tables_priv", st_relay_log_info::RELOAD_GRANT_F },
- { "user", st_relay_log_info::RELOAD_ACCESS_F }
-};
-
-static const my_size_t s_mysql_tables_size =
- sizeof(s_mysql_tables)/sizeof(*s_mysql_tables);
-
-static int reload_entry_compare(const void *lhs, const void *rhs)
-{
- const char *lstr = static_cast<const char *>(lhs);
- const char *rstr = static_cast<const st_reload_entry*>(rhs)->table;
- DBUG_ENTER("reload_entry_compare");
-
- DBUG_RETURN(strcmp(lstr, rstr));
-}
-
-void st_relay_log_info::touching_table(char const* db, char const* table,
- ulong table_id)
-{
- DBUG_ENTER("st_relay_log_info::touching_table");
-
- if (strcmp(db,"mysql") == 0)
- {
-#if defined(HAVE_BSEARCH) && defined(HAVE_SIZE_T)
- void *const ptr= bsearch(table, s_mysql_tables,
- s_mysql_tables_size,
- sizeof(*s_mysql_tables), reload_entry_compare);
- st_reload_entry const *const entry= static_cast<st_reload_entry*>(ptr);
-#else
- /*
- Fall back to full scan, there are few rows anyway and updating the
- "mysql" database is rare.
- */
- st_reload_entry const *entry= s_mysql_tables;
- for ( ; entry < s_mysql_tables + s_mysql_tables_size ; entry++)
- if (reload_entry_compare(table, entry) == 0)
- break;
-#endif
- if (entry)
- m_reload_flags|= entry->flag;
- }
- DBUG_VOID_RETURN;
-}
-
-void st_relay_log_info::transaction_end(THD* thd)
-{
- DBUG_ENTER("st_relay_log_info::transaction_end");
-
- if (m_reload_flags != RELOAD_NONE_F)
- {
- if (m_reload_flags & RELOAD_ACCESS_F)
- acl_reload(thd);
-
- if (m_reload_flags & RELOAD_GRANT_F)
- grant_reload(thd);
-
- m_reload_flags= RELOAD_NONE_F;
- }
- DBUG_VOID_RETURN;
-}
-
-#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
-void st_relay_log_info::cleanup_context(THD *thd, bool error)
-{
- DBUG_ENTER("st_relay_log_info::cleanup_context");
-
- DBUG_ASSERT(sql_thd == thd);
- /*
- 1) Instances of Table_map_log_event, if ::exec_event() was called on them,
- may have opened tables, which we cannot be sure have been closed (because
- maybe the Rows_log_event have not been found or will not be, because slave
- SQL thread is stopping, or relay log has a missing tail etc). So we close
- all thread's tables. And so the table mappings have to be cancelled.
- 2) Rows_log_event::exec_event() may even have started statements or
- transactions on them, which we need to rollback in case of error.
- 3) If finding a Format_description_log_event after a BEGIN, we also need
- to rollback before continuing with the next events.
- 4) so we need this "context cleanup" function.
- */
- if (error)
- {
- ha_autocommit_or_rollback(thd, 1); // if a "statement transaction"
- end_trans(thd, ROLLBACK); // if a "real transaction"
- }
- m_table_map.clear_tables();
- close_thread_tables(thd);
- clear_tables_to_lock();
- unsafe_to_stop_at= 0;
- DBUG_VOID_RETURN;
-}
-#endif
-
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List_iterator<i_string>;
diff --git a/sql/slave.h b/sql/slave.h
index e70b2e4b326..24ba09d78d3 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -24,6 +24,7 @@
#include "rpl_filter.h"
#include "rpl_tblmap.h"
#include "rpl_rli.h"
+#include "rpl_mi.h"
#define SLAVE_NET_TIMEOUT 3600
@@ -38,11 +39,11 @@
I/O Thread - One of these threads is started for each master server.
They maintain a connection to their master server, read log
events from the master as they arrive, and queues them into
- a single, shared relay log file. A MASTER_INFO struct
+ a single, shared relay log file. A MASTER_INFO
represents each of these threads.
SQL Thread - One of these threads is started and reads from the relay log
- file, executing each event. A RELAY_LOG_INFO struct
+ file, executing each event. A RELAY_LOG_INFO
represents this thread.
Buffering in the relay log file makes it unnecessary to reread events from
@@ -95,7 +96,6 @@ extern my_string opt_relay_logname, opt_relaylog_index_name;
extern my_bool opt_skip_slave_start, opt_reckless_slave;
extern my_bool opt_log_slave_updates;
extern ulonglong relay_log_space_limit;
-struct st_master_info;
/*
3 possible values for MASTER_INFO::slave_running and
@@ -114,110 +114,6 @@ struct st_master_info;
static Log_event* next_event(RELAY_LOG_INFO* rli);
-/*****************************************************************************
-
- Replication IO Thread
-
- st_master_info contains:
- - information about how to connect to a master
- - current master log name
- - current master log offset
- - misc control variables
-
- st_master_info is initialized once from the master.info file if such
- exists. Otherwise, data members corresponding to master.info fields
- are initialized with defaults specified by master-* options. The
- initialization is done through init_master_info() call.
-
- The format of master.info file:
-
- log_name
- log_pos
- master_host
- master_user
- master_pass
- master_port
- master_connect_retry
-
- To write out the contents of master.info file to disk ( needed every
- time we read and queue data from the master ), a call to
- flush_master_info() is required.
-
- To clean up, call end_master_info()
-
-*****************************************************************************/
-
-typedef struct st_master_info
-{
- /* the variables below are needed because we can change masters on the fly */
- char master_log_name[FN_REFLEN];
- char host[HOSTNAME_LENGTH+1];
- char user[USERNAME_LENGTH+1];
- char password[MAX_PASSWORD_LENGTH+1];
- my_bool ssl; // enables use of SSL connection if true
- char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
- char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
-
- my_off_t master_log_pos;
- File fd; // we keep the file open, so we need to remember the file pointer
- IO_CACHE file;
-
- pthread_mutex_t data_lock,run_lock;
- pthread_cond_t data_cond,start_cond,stop_cond;
- THD *io_thd;
- MYSQL* mysql;
- uint32 file_id; /* for 3.23 load data infile */
- RELAY_LOG_INFO rli;
- uint port;
- uint connect_retry;
-#ifndef DBUG_OFF
- int events_till_disconnect;
-#endif
- bool inited;
- volatile bool abort_slave;
- volatile uint slave_running;
- volatile ulong slave_run_id;
- /*
- The difference in seconds between the clock of the master and the clock of
- the slave (second - first). It must be signed as it may be <0 or >0.
- clock_diff_with_master is computed when the I/O thread starts; for this the
- I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
- "how late the slave is compared to the master" is computed like this:
- clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
-
- */
- long clock_diff_with_master;
-
- st_master_info()
- :ssl(0), fd(-1), io_thd(0), inited(0),
- abort_slave(0),slave_running(0), slave_run_id(0)
- {
- host[0] = 0; user[0] = 0; password[0] = 0;
- ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
- ssl_cipher[0]= 0; ssl_key[0]= 0;
-
- bzero((char*) &file, sizeof(file));
- pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&data_cond, NULL);
- pthread_cond_init(&start_cond, NULL);
- pthread_cond_init(&stop_cond, NULL);
- }
-
- ~st_master_info()
- {
- pthread_mutex_destroy(&run_lock);
- pthread_mutex_destroy(&data_lock);
- pthread_cond_destroy(&data_cond);
- pthread_cond_destroy(&start_cond);
- pthread_cond_destroy(&stop_cond);
- }
-
-} MASTER_INFO;
-
-
-int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
-
#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
"FIRST")
#define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\
@@ -231,7 +127,6 @@ int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
int init_slave();
void init_slave_skip_errors(const char* arg);
-int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache);
bool flush_relay_log_info(RELAY_LOG_INFO* rli);
int register_slave_on_master(MYSQL* mysql);
int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,
@@ -276,14 +171,8 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli,
ATTRIBUTE_FORMAT(printf, 4, 5);
void end_slave(); /* clean up */
-void init_master_info_with_options(MASTER_INFO* mi);
void clear_until_condition(RELAY_LOG_INFO* rli);
void clear_slave_error(RELAY_LOG_INFO* rli);
-int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
- const char* slave_info_fname,
- bool abort_if_no_master_info_file,
- int thread_mask);
-void end_master_info(MASTER_INFO* mi);
void end_relay_log_info(RELAY_LOG_INFO* rli);
void lock_slave_threads(MASTER_INFO* mi);
void unlock_slave_threads(MASTER_INFO* mi);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 47a623ec749..622d9efdde0 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -899,7 +899,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
break;
val= (*splocal)->this_item();
- DBUG_PRINT("info", ("print %p", val));
+ DBUG_PRINT("info", ("print 0x%lx", (long) val));
str_value= sp_get_item_value(val, &str_value_holder);
if (str_value)
res|= qbuf.append(*str_value);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index aa13c2f08f4..721b6b5a003 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3871,7 +3871,7 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
GRANT_COLUMN *grant_column;
ulong want_access= grant->want_privilege & ~grant->privilege;
DBUG_ENTER("check_grant_column");
- DBUG_PRINT("enter", ("table: %s want_access: %u", table_name, want_access));
+ DBUG_PRINT("enter", ("table: %s want_access: %lu", table_name, want_access));
if (!want_access)
DBUG_RETURN(0); // Already checked
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 28bc1e9dcbf..f1a685778f9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1087,7 +1087,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
if (!lock_in_use)
VOID(pthread_mutex_lock(&LOCK_open));
- DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables));
+ DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables));
found_old_table= 0;
while (thd->open_tables)
@@ -1177,6 +1177,16 @@ static inline uint tmpkeyval(THD *thd, TABLE *table)
void close_temporary_tables(THD *thd)
{
TABLE *table;
+ TABLE *next;
+ /*
+ TODO: 5.1 maintains prev link in temporary_tables
+ double-linked list so we could fix it. But it is not necessary
+ at this time when the list is being destroyed
+ */
+ TABLE *prev_table;
+ /* Assume thd->options has OPTION_QUOTE_SHOW_CREATE */
+ bool was_quote_show= TRUE;
+
if (!thd->temporary_tables)
return;
@@ -1192,12 +1202,7 @@ void close_temporary_tables(THD *thd)
return;
}
- TABLE *next,
- *prev_table /* TODO: 5.1 maintaines prev link in temporary_tables
- double-linked list so we could fix it. But it is not necessary
- at this time when the list is being destroyed */;
- 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
+ /* 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];
@@ -1303,7 +1308,7 @@ void close_temporary_tables(THD *thd)
}
}
if (!was_quote_show)
- thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
+ thd->options&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
thd->temporary_tables=0;
}
@@ -2069,7 +2074,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(0); // VIEW
}
- DBUG_PRINT("info", ("inserting table %p into the cache", table));
+ DBUG_PRINT("info", ("inserting table 0x%lx into the cache", (long) table));
VOID(my_hash_insert(&open_cache,(byte*) table));
}
@@ -2399,7 +2404,7 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
{
DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d "
"locked_by_flush: %d locked_by_name: %d "
- "db_stat: %u version: %u",
+ "db_stat: %u version: %lu",
(ulong) search->s, search->locked_by_logger,
search->locked_by_flush, search->locked_by_name,
search->db_stat,
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index 23ca5330053..37094b992e5 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -79,9 +79,16 @@ void mysql_client_binlog_statement(THD* thd)
char const *endptr= 0;
int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr);
+#ifndef HAVE_purify
+ /*
+ This debug printout should not be used for valgrind builds
+ since it will read from unassigned memory.
+ */
DBUG_PRINT("info",
- ("bytes_decoded=%d; strptr=0x%lu; endptr=0x%lu ('%c':%d)",
- bytes_decoded, strptr, endptr, *endptr, *endptr));
+ ("bytes_decoded: %d strptr: 0x%lx endptr: 0x%lx ('%c':%d)",
+ bytes_decoded, (long) strptr, (long) endptr, *endptr,
+ *endptr));
+#endif
if (bytes_decoded < 0)
{
@@ -107,8 +114,8 @@ void mysql_client_binlog_statement(THD* thd)
order to be able to read exactly what is necessary.
*/
- DBUG_PRINT("info",("binlog base64 decoded_len=%d, bytes_decoded=%d",
- decoded_len, bytes_decoded));
+ DBUG_PRINT("info",("binlog base64 decoded_len: %lu bytes_decoded: %d",
+ (ulong) decoded_len, bytes_decoded));
/*
Now we start to read events of the buffer, until there are no
@@ -145,14 +152,21 @@ void mysql_client_binlog_statement(THD* thd)
bufptr += event_len;
DBUG_PRINT("info",("ev->get_type_code()=%d", ev->get_type_code()));
- DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET=0x%lx",
- bufptr+EVENT_TYPE_OFFSET));
- DBUG_PRINT("info", ("bytes_decoded=%d; bufptr=0x%lx; buf[EVENT_LEN_OFFSET]=%u",
- bytes_decoded, bufptr, uint4korr(bufptr+EVENT_LEN_OFFSET)));
+#ifndef HAVE_purify
+ /*
+ This debug printout should not be used for valgrind builds
+ since it will read from unassigned memory.
+ */
+ DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET: 0x%lx",
+ (long) (bufptr+EVENT_TYPE_OFFSET)));
+ DBUG_PRINT("info", ("bytes_decoded: %d bufptr: 0x%lx buf[EVENT_LEN_OFFSET]: %lu",
+ bytes_decoded, (long) bufptr,
+ (ulong) uint4korr(bufptr+EVENT_LEN_OFFSET)));
+#endif
ev->thd= thd;
if (int err= ev->exec_event(thd->rli_fake))
{
- DBUG_PRINT("info", ("exec_event() - error=%d", error));
+ DBUG_PRINT("error", ("exec_event() returned: %d", err));
/*
TODO: Maybe a better error message since the BINLOG statement
now contains several events.
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index ee3b8aa79fe..3362ec76fc2 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -523,7 +523,8 @@ void Query_cache_query::init_n_lock()
my_rwlock_init(&lock, NULL);
lock_writing();
DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ (long) (((byte*) this) -
+ ALIGN_SIZE(sizeof(Query_cache_block)))));
DBUG_VOID_RETURN;
}
@@ -532,7 +533,8 @@ void Query_cache_query::unlock_n_destroy()
{
DBUG_ENTER("Query_cache_query::unlock_n_destroy");
DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ (long) (((byte*) this) -
+ ALIGN_SIZE(sizeof(Query_cache_block)))));
/*
The following call is not needed on system where one can destroy an
active semaphore
@@ -698,6 +700,7 @@ void query_cache_abort(NET *net)
void query_cache_end_of_result(THD *thd)
{
+ Query_cache_block *query_block;
DBUG_ENTER("query_cache_end_of_result");
/* See the comment on double-check locking usage above. */
@@ -713,13 +716,9 @@ void query_cache_end_of_result(THD *thd)
if (unlikely(query_cache.query_cache_size == 0 ||
query_cache.flush_in_progress))
- {
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
- DBUG_VOID_RETURN;
- }
+ goto end;
- Query_cache_block *query_block= ((Query_cache_block*)
- thd->net.query_cache_query);
+ query_block= ((Query_cache_block*) thd->net.query_cache_query);
if (query_block)
{
DUMP(&query_cache);
@@ -738,27 +737,21 @@ void query_cache_end_of_result(THD *thd)
header->query()));
query_cache.wreck(__LINE__, "");
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
-
- DBUG_VOID_RETURN;
+ BLOCK_UNLOCK_WR(query_block);
+ goto end;
}
#endif
header->found_rows(current_thd->limit_found_rows);
header->result()->type= Query_cache_block::RESULT;
header->writer(0);
thd->net.query_cache_query= 0;
+ BLOCK_UNLOCK_WR(query_block);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
-
- BLOCK_UNLOCK_WR(query_block);
- }
- else
- {
- // Cache was flushed or resized and query was deleted => do nothing
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
}
+end:
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
DBUG_VOID_RETURN;
}
@@ -875,8 +868,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
flags.character_set_client_num,
flags.character_set_results_num,
flags.collation_connection_num,
- flags.limit,
- (ulong)flags.time_zone,
+ (ulong) flags.limit,
+ (ulong) flags.time_zone,
flags.sql_mode,
flags.max_sort_length,
flags.group_concat_max_len));
@@ -1119,8 +1112,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
flags.character_set_client_num,
flags.character_set_results_num,
flags.collation_connection_num,
- flags.limit,
- (ulong)flags.time_zone,
+ (ulong) flags.limit,
+ (ulong) flags.time_zone,
flags.sql_mode,
flags.max_sort_length,
flags.group_concat_max_len));
@@ -1234,9 +1227,9 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
if (engine_data != table->engine_data())
{
DBUG_PRINT("qcache",
- ("Handler require invalidation queries of %s.%s %lld-%lld",
- table_list.db, table_list.alias,
- engine_data, table->engine_data()));
+ ("Handler require invalidation queries of %s.%s %lu-%lu",
+ table_list.db, table_list.alias,
+ (ulong) engine_data, (ulong) table->engine_data()));
invalidate_table((byte *) table->db(), table->key_length());
}
else
@@ -1257,10 +1250,10 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
#ifndef EMBEDDED_LIBRARY
do
{
- DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
+ DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)",
result_block->length, result_block->used,
- result_block->headers_len()+
- ALIGN_SIZE(sizeof(Query_cache_result))));
+ (ulong) (result_block->headers_len()+
+ ALIGN_SIZE(sizeof(Query_cache_result)))));
Query_cache_result *result = result_block->result();
if (net_real_write(&thd->net, result->data(),
@@ -2034,7 +2027,7 @@ Query_cache::append_result_data(Query_cache_block **current_block,
{
DBUG_ENTER("Query_cache::append_result_data");
DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
- data_len, query_block));
+ data_len, (long) query_block));
if (query_block->query()->add(data_len) > query_cache_limit)
{
@@ -2476,11 +2469,11 @@ Query_cache::insert_table(uint key_len, char *key,
table_block->table()->engine_data() != engine_data)
{
DBUG_PRINT("qcache",
- ("Handler require invalidation queries of %s.%s %lld-%lld",
+ ("Handler require invalidation queries of %s.%s %lu-%lu",
table_block->table()->db(),
table_block->table()->table(),
- engine_data,
- table_block->table()->engine_data()));
+ (ulong) engine_data,
+ (ulong) table_block->table()->engine_data()));
/*
as far as we delete all queries with this table, table block will be
deleted, too
@@ -2988,7 +2981,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
DBUG_PRINT("qcache", ("table: %s db: %s type: %u",
tables_used->table->s->table_name.str,
tables_used->table->s->db.str,
- tables_used->table->s->db_type));
+ tables_used->table->s->db_type->db_type));
if (tables_used->derived)
{
table_count--;
@@ -3043,10 +3036,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
OPTION_TO_QUERY_CACHE))) &&
lex->safe_to_cache_query)
{
- DBUG_PRINT("qcache", ("options %lx %lx, type %u",
- OPTION_TO_QUERY_CACHE,
- lex->select_lex.options,
- (int) thd->variables.query_cache_type));
+ DBUG_PRINT("qcache", ("options: %lx %lx type: %u",
+ (long) OPTION_TO_QUERY_CACHE,
+ (long) lex->select_lex.options,
+ (int) thd->variables.query_cache_type));
if (!(table_count= process_and_count_tables(tables_used, tables_type)))
DBUG_RETURN(0);
@@ -3062,10 +3055,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
}
DBUG_PRINT("qcache",
- ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
+ ("not interesting query: %d or not cacheable, options %lx %lx type: %u",
(int) lex->sql_command,
- OPTION_TO_QUERY_CACHE,
- lex->select_lex.options,
+ (long) OPTION_TO_QUERY_CACHE,
+ (long) lex->select_lex.options,
(int) thd->variables.query_cache_type));
DBUG_RETURN(0);
}
@@ -3656,7 +3649,8 @@ void Query_cache::queries_dump()
DBUG_PRINT("qcache", ("F:%u C:%u L:%lu T:'%s' (%u) '%s' '%s'",
flags.client_long_flag,
flags.character_set_client_num,
- (ulong)flags.limit, flags.time_zone->get_name(),
+ (ulong)flags.limit,
+ flags.time_zone->get_name()->ptr(),
len, str, strend(str)+1));
DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
(ulong) block->next, (ulong) block->prev,
@@ -3765,7 +3759,7 @@ my_bool Query_cache::check_integrity(bool locked)
{
DBUG_PRINT("error",
("block 0x%lx do not aligned by %d", (ulong) block,
- ALIGN_SIZE(1)));
+ (int) ALIGN_SIZE(1)));
result = 1;
}
// Check memory allocation
@@ -3876,9 +3870,8 @@ my_bool Query_cache::check_integrity(bool locked)
break;
}
default:
- DBUG_PRINT("error",
- ("block 0x%lx have incorrect type %u",
- block, block->type));
+ DBUG_PRINT("error", ("block 0x%lx have incorrect type %u",
+ (long) block, block->type));
result = 1;
}
@@ -3976,8 +3969,8 @@ my_bool Query_cache::check_integrity(bool locked)
} while (block != bins[i].free_blocks);
if (count != bins[i].number)
{
- DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks",
- bins[i].number, count));
+ DBUG_PRINT("error", ("bins[%d].number = %d, but bin have %d blocks",
+ i, bins[i].number, count));
result = 1;
}
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 776ba4dabea..07510c1fbb0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -551,7 +551,7 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
void THD::awake(THD::killed_state state_to_set)
{
DBUG_ENTER("THD::awake");
- DBUG_PRINT("enter", ("this=0x%lx", this));
+ DBUG_PRINT("enter", ("this: 0x%lx", (long) this));
THD_CHECK_SENTRY(this);
safe_mutex_assert_owner(&LOCK_delete);
@@ -799,7 +799,7 @@ void THD::add_changed_table(const char *key, long key_length)
{
list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length, (*prev_changed)->key_length));
+ ("key_length %ld %u", key_length, (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -809,7 +809,7 @@ void THD::add_changed_table(const char *key, long key_length)
{
list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length,
+ ("key_length %ld %u", key_length,
(*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
@@ -821,7 +821,7 @@ void THD::add_changed_table(const char *key, long key_length)
}
}
*prev_changed = changed_table_dup(key, key_length);
- DBUG_PRINT("info", ("key_length %u %u", key_length,
+ DBUG_PRINT("info", ("key_length %ld %u", key_length,
(*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
@@ -2518,7 +2518,9 @@ my_size_t THD::max_row_length_blob(TABLE *table, const byte *data) const
for (uint *ptr= beg ; ptr != end ; ++ptr)
{
Field_blob* const blob= (Field_blob*) table->field[*ptr];
- length+= blob->get_length((const char *) (data + blob->offset())) + 2;
+ length+= blob->get_length((const char*) (data +
+ blob->offset(table->record[0]))) +
+ HA_KEY_BLOB_LENGTH;
}
return length;
@@ -2552,6 +2554,128 @@ my_size_t THD::pack_row(TABLE *table, MY_BITMAP const* cols, byte *row_data,
}
+namespace {
+ /**
+ Class to handle temporary allocation of memory for row data.
+
+ The responsibilities of the class is to provide memory for
+ packing one or two rows of packed data (depending on what
+ constructor is called).
+
+ In order to make the allocation more efficient for "simple" rows,
+ i.e., rows that do not contain any blobs, a pointer to the
+ allocated memory is of memory is stored in the table structure
+ for simple rows. If memory for a table containing a blob field
+ is requested, only memory for that is allocated, and subsequently
+ released when the object is destroyed.
+
+ */
+ class Row_data_memory {
+ public:
+ /**
+ Build an object to keep track of a block-local piece of memory
+ for storing a row of data.
+
+ @param table
+ Table where the pre-allocated memory is stored.
+
+ @param length
+ Length of data that is needed, if the record contain blobs.
+ */
+ Row_data_memory(TABLE *table, my_size_t const len1)
+ : m_memory(0)
+ {
+#ifndef DBUG_OFF
+ m_alloc_checked= false;
+#endif
+ allocate_memory(table, len1);
+ m_ptr[0]= has_memory() ? m_memory : 0;
+ m_ptr[1]= 0;
+ }
+
+ Row_data_memory(TABLE *table, my_size_t const len1, my_size_t const len2)
+ : m_memory(0)
+ {
+#ifndef DBUG_OFF
+ m_alloc_checked= false;
+#endif
+ allocate_memory(table, len1 + len2);
+ m_ptr[0]= has_memory() ? m_memory : 0;
+ m_ptr[1]= has_memory() ? m_memory + len1 : 0;
+ }
+
+ ~Row_data_memory()
+ {
+ if (m_memory != 0 && m_release_memory_on_destruction)
+ my_free((gptr) m_memory, MYF(MY_WME));
+ }
+
+ /**
+ Is there memory allocated?
+
+ @retval true There is memory allocated
+ @retval false Memory allocation failed
+ */
+ bool has_memory() const {
+#ifndef DBUG_OFF
+ m_alloc_checked= true;
+#endif
+ return m_memory != 0;
+ }
+
+ byte *slot(uint s)
+ {
+ DBUG_ASSERT(s < sizeof(m_ptr)/sizeof(*m_ptr));
+ DBUG_ASSERT(m_ptr[s] != 0);
+ DBUG_ASSERT(m_alloc_checked == true);
+ return m_ptr[s];
+ }
+
+ private:
+ void allocate_memory(TABLE *const table, my_size_t const total_length)
+ {
+ if (table->s->blob_fields == 0)
+ {
+ /*
+ The maximum length of a packed record is less than this
+ length. We use this value instead of the supplied length
+ when allocating memory for records, since we don't know how
+ the memory will be used in future allocations.
+
+ Since table->s->reclength is for unpacked records, we have
+ to add two bytes for each field, which can potentially be
+ added to hold the length of a packed field.
+ */
+ my_size_t const maxlen= table->s->reclength + 2 * table->s->fields;
+
+ /*
+ Allocate memory for two records if memory hasn't been
+ allocated. We allocate memory for two records so that it can
+ be used when processing update rows as well.
+ */
+ if (table->write_row_record == 0)
+ table->write_row_record=
+ (byte *) alloc_root(&table->mem_root, 2 * maxlen);
+ m_memory= table->write_row_record;
+ m_release_memory_on_destruction= false;
+ }
+ else
+ {
+ m_memory= (byte *) my_malloc(total_length, MYF(MY_WME));
+ m_release_memory_on_destruction= true;
+ }
+ }
+
+#ifndef DBUG_OFF
+ mutable bool m_alloc_checked;
+#endif
+ bool m_release_memory_on_destruction;
+ byte *m_memory;
+ byte *m_ptr[2];
+ };
+}
+
+
int THD::binlog_write_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, my_size_t colcnt,
byte const *record)
@@ -2562,40 +2686,25 @@ int THD::binlog_write_row(TABLE* table, bool is_trans,
Pack records into format for transfer. We are allocating more
memory than needed, but that doesn't matter.
*/
- bool error= 0;
- byte *row_data= table->write_row_record;
- my_size_t const max_len= max_row_length(table, record);
- my_size_t len;
- Rows_log_event *ev;
-
- /* Allocate room for a row (if needed) */
- if (!row_data)
- {
- if (!table->s->blob_fields)
- {
- /* multiply max_len by 2 so it can be used for update_row as well */
- table->write_row_record= (byte *) alloc_root(&table->mem_root,
- 2*max_len);
- if (!table->write_row_record)
- return HA_ERR_OUT_OF_MEM;
- row_data= table->write_row_record;
- }
- else if (unlikely(!(row_data= (byte *) my_malloc(max_len, MYF(MY_WME)))))
- return HA_ERR_OUT_OF_MEM;
- }
- len= pack_row(table, cols, row_data, record);
+ int error= 0;
- ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
- len, is_trans,
- static_cast<Write_rows_log_event*>(0));
+ Row_data_memory memory(table, max_row_length(table, record));
+ if (!memory.has_memory())
+ return HA_ERR_OUT_OF_MEM;
- /* add_row_data copies row_data to internal buffer */
- error= likely(ev != 0) ? ev->add_row_data(row_data,len) : HA_ERR_OUT_OF_MEM ;
+ byte *row_data= memory.slot(0);
- if (table->write_row_record == 0)
- my_free((gptr) row_data, MYF(MY_WME));
+ my_size_t const len= pack_row(table, cols, row_data, record);
- return error;
+ Rows_log_event* const ev=
+ binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
+ len, is_trans,
+ static_cast<Write_rows_log_event*>(0));
+
+ if (unlikely(ev == 0))
+ return HA_ERR_OUT_OF_MEM;
+
+ return ev->add_row_data(row_data, len);
}
int THD::binlog_update_row(TABLE* table, bool is_trans,
@@ -2605,53 +2714,44 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
{
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
- bool error= 0;
+ int error= 0;
my_size_t const before_maxlen = max_row_length(table, before_record);
my_size_t const after_maxlen = max_row_length(table, after_record);
- byte *row_data= table->write_row_record;
- byte *before_row, *after_row;
- if (row_data != 0)
- {
- before_row= row_data;
- after_row= before_row + before_maxlen;
- }
- else
- {
- if (unlikely(!(row_data= (byte*)my_multi_malloc(MYF(MY_WME),
- &before_row, before_maxlen,
- &after_row, after_maxlen,
- NULL))))
- return HA_ERR_OUT_OF_MEM;
- }
+ Row_data_memory row_data(table, before_maxlen, after_maxlen);
+ if (!row_data.has_memory())
+ return HA_ERR_OUT_OF_MEM;
+
+ byte *before_row= row_data.slot(0);
+ byte *after_row= row_data.slot(1);
my_size_t const before_size= pack_row(table, cols, before_row,
before_record);
my_size_t const after_size= pack_row(table, cols, after_row,
after_record);
-
+
+ /*
+ Don't print debug messages when running valgrind since they can
+ trigger false warnings.
+ */
+#ifndef HAVE_purify
DBUG_DUMP("before_record", (const char *)before_record, table->s->reclength);
DBUG_DUMP("after_record", (const char *)after_record, table->s->reclength);
DBUG_DUMP("before_row", (const char *)before_row, before_size);
DBUG_DUMP("after_row", (const char *)after_row, after_size);
+#endif
Rows_log_event* const ev=
binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
before_size + after_size, is_trans,
static_cast<Update_rows_log_event*>(0));
- error=
- unlikely(!ev) ||
+ if (unlikely(ev == 0))
+ return HA_ERR_OUT_OF_MEM;
+
+ return
ev->add_row_data(before_row, before_size) ||
ev->add_row_data(after_row, after_size);
-
- if (!table->write_row_record)
- {
- /* add_row_data copies row_data to internal buffer */
- my_free((gptr)row_data, MYF(MY_WME));
- }
-
- return error;
}
int THD::binlog_delete_row(TABLE* table, bool is_trans,
@@ -2664,11 +2764,14 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
Pack records into format for transfer. We are allocating more
memory than needed, but that doesn't matter.
*/
- bool error= 0;
- my_size_t const max_len= max_row_length(table, record);
- byte *row_data= table->write_row_record;
- if (!row_data && unlikely(!(row_data= (byte*)my_malloc(max_len, MYF(MY_WME)))))
+ int error= 0;
+
+ Row_data_memory memory(table, max_row_length(table, record));
+ if (unlikely(!memory.has_memory()))
return HA_ERR_OUT_OF_MEM;
+
+ byte *row_data= memory.slot(0);
+
my_size_t const len= pack_row(table, cols, row_data, record);
Rows_log_event* const ev=
@@ -2676,13 +2779,10 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
len, is_trans,
static_cast<Delete_rows_log_event*>(0));
- error= (unlikely(!ev)) || ev->add_row_data(row_data, len);
-
- /* add_row_data copies row_data */
- if (table->write_row_record == 0)
- my_free((gptr)row_data, MYF(MY_WME));
+ if (unlikely(ev == 0))
+ return HA_ERR_OUT_OF_MEM;
- return error;
+ return ev->add_row_data(row_data, len);
}
@@ -2776,6 +2876,12 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
#endif /*HAVE_ROW_BASED_REPLICATION*/
switch (qtype) {
+ case THD::ROW_QUERY_TYPE:
+#ifdef HAVE_ROW_BASED_REPLICATION
+ if (current_stmt_binlog_row_based)
+ DBUG_RETURN(0);
+#endif
+ /* Otherwise, we fall through */
case THD::MYSQL_QUERY_TYPE:
/*
Using this query type is a conveniece hack, since we have been
@@ -2785,12 +2891,6 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
Make sure to change in check_table_binlog_row_based() according
to how you treat this.
*/
- case THD::ROW_QUERY_TYPE:
-#ifdef HAVE_ROW_BASED_REPLICATION
- if (current_stmt_binlog_row_based)
- DBUG_RETURN(0);
-#endif
- /* Otherwise, we fall through */
case THD::STMT_QUERY_TYPE:
/*
The MYSQL_LOG::write() function will set the STMT_END_F flag and
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2cf7de5ee9e..e6f2ec7b041 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -425,6 +425,12 @@ public:
{ return strdup_root(mem_root,str); }
inline char *strmake(const char *str, uint size)
{ return strmake_root(mem_root,str,size); }
+ inline bool LEX_STRING_make(LEX_STRING *lex_str, const char *str, uint size)
+ {
+ return ((lex_str->str=
+ strmake_root(mem_root, str, (lex_str->length= size)))) == 0;
+ }
+
inline char *memdup(const char *str, uint size)
{ return memdup_root(mem_root,str,size); }
inline char *memdup_w_gap(const char *str, uint size, uint gap)
@@ -1628,8 +1634,7 @@ public:
return TRUE;
}
*p_db= strmake(db, db_length);
- if (p_db_length)
- *p_db_length= db_length;
+ *p_db_length= db_length;
return FALSE;
}
};
@@ -2065,7 +2070,7 @@ public:
inline bool unique_add(void *ptr)
{
DBUG_ENTER("unique_add");
- DBUG_PRINT("info", ("tree %u - %u", tree.elements_in_tree, max_elements));
+ DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements));
if (tree.elements_in_tree > max_elements && flush())
DBUG_RETURN(1);
DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg));
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 37096fd897e..0c154069bd6 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1302,8 +1302,8 @@ err:
bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
{
- int path_length, db_length;
- char *db_name;
+ int path_length;
+ LEX_STRING db_name;
bool system_db= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong db_access;
@@ -1323,25 +1323,26 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
/* Called from SP to restore the original database, which was NULL */
DBUG_ASSERT(no_access_check);
system_db= 1;
- db_name= NULL;
- db_length= 0;
+ db_name.str= NULL;
+ db_name.length= 0;
goto end;
}
/*
Now we need to make a copy because check_db_name requires a
non-constant argument. TODO: fix check_db_name.
*/
- if ((db_name= my_strdup(name, MYF(MY_WME))) == NULL)
+ if ((db_name.str= my_strdup(name, MYF(MY_WME))) == NULL)
DBUG_RETURN(1); /* the error is set */
- db_length= strlen(db_name);
- if (check_db_name(db_name))
+ db_name.length= strlen(db_name.str);
+ if (check_db_name(&db_name))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db_name);
- my_free(db_name, MYF(0));
+ my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
+ my_free(db_name.str, MYF(0));
DBUG_RETURN(1);
}
- DBUG_PRINT("info",("Use database: %s", db_name));
- if (!my_strcasecmp(system_charset_info, db_name, information_schema_name.str))
+ DBUG_PRINT("info",("Use database: %s", db_name.str));
+ if (!my_strcasecmp(system_charset_info, db_name.str,
+ information_schema_name.str))
{
system_db= 1;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1356,34 +1357,35 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
if (test_all_bits(sctx->master_access, DB_ACLS))
db_access=DB_ACLS;
else
- db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name, 0) |
+ db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user,
+ db_name.str, 0) |
sctx->master_access);
if (!(db_access & DB_ACLS) && (!grant_option ||
- check_grant_db(thd,db_name)))
+ check_grant_db(thd, db_name.str)))
{
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user,
sctx->priv_host,
- db_name);
+ db_name.str);
general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR),
- sctx->priv_user, sctx->priv_host, db_name);
- my_free(db_name,MYF(0));
+ sctx->priv_user, sctx->priv_host, db_name.str);
+ my_free(db_name.str, MYF(0));
DBUG_RETURN(1);
}
}
#endif
- if (check_db_dir_existence(db_name))
+ if (check_db_dir_existence(db_name.str))
{
- my_error(ER_BAD_DB_ERROR, MYF(0), db_name);
- my_free(db_name, MYF(0));
+ my_error(ER_BAD_DB_ERROR, MYF(0), db_name.str);
+ my_free(db_name.str, MYF(0));
DBUG_RETURN(1);
}
end:
x_free(thd->db);
- DBUG_ASSERT(db_name == NULL || db_name[0] != '\0');
- thd->reset_db(db_name, db_length); // THD::~THD will free this
+ DBUG_ASSERT(db_name.str == NULL || db_name.str[0] != '\0');
+ thd->reset_db(db_name.str, db_name.length); // THD::~THD will free this
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!no_access_check)
sctx->db_access= db_access;
@@ -1397,7 +1399,7 @@ end:
{
HA_CREATE_INFO create;
- load_db_opt_by_name(thd, db_name, &create);
+ load_db_opt_by_name(thd, db_name.str, &create);
thd->db_charset= create.default_table_charset ?
create.default_table_charset :
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index a0cd419e6c6..5da2a7660a4 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -354,7 +354,7 @@ cleanup:
{
thd->row_count_func= deleted;
send_ok(thd,deleted);
- DBUG_PRINT("info",("%d records deleted",deleted));
+ DBUG_PRINT("info",("%ld records deleted",(long) deleted));
}
DBUG_RETURN(error >= 0 || thd->net.report_error);
}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 0d893a6c9be..c448be04ac5 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -367,9 +367,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
strlen(tables->alias) + 1)))
{
table= hash_tables->table;
- DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
+ DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' table: 0x%lx",
hash_tables->db, hash_tables->table_name,
- hash_tables->alias, table));
+ hash_tables->alias, (long) table));
if (!table)
{
/*
@@ -633,7 +633,8 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
TABLE **table_ptr;
bool did_lock= FALSE;
DBUG_ENTER("mysql_ha_flush");
- DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags));
+ DBUG_PRINT("enter", ("tables: 0x%lx mode_flags: 0x%02x",
+ (long) tables, mode_flags));
if (tables)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1c2d2cc1100..cfdc2954688 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -176,7 +176,8 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->reset_query_tables_list(FALSE);
lex->expr_allows_subselect= TRUE;
- lex->name= 0;
+ lex->name.str= 0;
+ lex->name.length= 0;
lex->event_parse_data= NULL;
lex->nest_level=0 ;
@@ -1449,7 +1450,7 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
{
DBUG_ENTER("st_select_lex::add_item_to_list");
- DBUG_PRINT("info", ("Item: %p", item));
+ DBUG_PRINT("info", ("Item: 0x%lx", (long) item));
DBUG_RETURN(item_list.push_back(item));
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e8f275d5caf..be508032c35 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -908,7 +908,8 @@ typedef struct st_lex : public Query_tables_list
/* The values of tok_start/tok_end as they were one call of MYSQLlex before */
const uchar *tok_start_prev, *tok_end_prev;
- char *length,*dec,*change,*name;
+ char *length,*dec,*change;
+ LEX_STRING name;
Table_ident *like_name;
char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d88478b9702..9f981fb6bc6 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -394,9 +394,9 @@ int check_user(THD *thd, enum enum_server_command command,
NO_ACCESS)) // authentication is OK
{
DBUG_PRINT("info",
- ("Capabilities: %lx packet_length: %ld Host: '%s' "
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
"Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %u db: '%s'",
+ "Access: %lu db: '%s'",
thd->client_capabilities,
thd->max_client_packet_length,
thd->main_security_ctx.host_or_ip,
@@ -1002,7 +1002,7 @@ static int check_connection(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
/* Do the SSL layering. */
@@ -1055,11 +1055,14 @@ static int check_connection(THD *thd)
Old clients send null-terminated string as password; new clients send
the size (1 byte) + string (not null-terminated). Hence in case of empty
password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
*/
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
db + passwd_len + 1 : 0;
+ /* strlen() can't be easily deleted without changing protocol */
uint db_len= db ? strlen(db) : 0;
if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
@@ -1158,7 +1161,7 @@ pthread_handler_t handle_one_connection(void *arg)
of handle_one_connection, which is thd. We need to know the
start of the stack so that we could check for stack overruns.
*/
- DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
+ DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n",
thd->thread_id));
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
@@ -1321,28 +1324,31 @@ pthread_handler_t handle_bootstrap(void *arg)
thd->init_for_queries();
while (fgets(buff, thd->net.max_packet, file))
{
- ulong length= (ulong) strlen(buff);
- while (buff[length-1] != '\n' && !feof(file))
- {
- /*
- We got only a part of the current string. Will try to increase
- net buffer then read the rest of the current string.
- */
- if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
- {
- net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
- thd->fatal_error();
- break;
- }
- buff= (char*) thd->net.buff;
- fgets(buff + length, thd->net.max_packet - length, file);
- length+= (ulong) strlen(buff + length);
- }
- if (thd->is_fatal_error)
- break;
+ /* strlen() can't be deleted because fgets() doesn't return length */
+ ulong length= (ulong) strlen(buff);
+ while (buff[length-1] != '\n' && !feof(file))
+ {
+ /*
+ We got only a part of the current string. Will try to increase
+ net buffer then read the rest of the current string.
+ */
+ /* purecov: begin tested */
+ if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
+ {
+ net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
+ thd->fatal_error();
+ break;
+ }
+ buff= (char*) thd->net.buff;
+ fgets(buff + length, thd->net.max_packet - length, file);
+ length+= (ulong) strlen(buff + length);
+ /* purecov: end */
+ }
+ if (thd->is_fatal_error)
+ break; /* purecov: inspected */
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
- buff[length-1] == ';'))
+ buff[length-1] == ';'))
length--;
buff[length]=0;
thd->query_length=length;
@@ -1427,24 +1433,30 @@ void cleanup_items(Item *item)
*/
static
-int mysql_table_dump(THD* thd, char* db, char* tbl_name)
+int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name)
{
TABLE* table;
TABLE_LIST* table_list;
int error = 0;
DBUG_ENTER("mysql_table_dump");
- db = (db && db[0]) ? db : thd->db;
+ if (db->length == 0)
+ {
+ db->str= thd->db; /* purecov: inspected */
+ db->length= thd->db_length; /* purecov: inspected */
+ }
if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory
- table_list->db= db;
+ table_list->db= db->str;
table_list->table_name= table_list->alias= tbl_name;
table_list->lock_type= TL_READ_NO_INSERT;
table_list->prev_global= &table_list; // can be removed after merge with 4.1
- if (!db || check_db_name(db))
+ if (check_db_name(db))
{
- my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL");
+ /* purecov: begin inspected */
+ my_error(ER_WRONG_DB_NAME ,MYF(0), db->str ? db->str : "NULL");
goto err;
+ /* purecov: end */
}
if (lower_case_table_names)
my_casedn_str(files_charset_info, tbl_name);
@@ -1604,7 +1616,7 @@ bool do_command(THD *thd)
command= COM_END; // Wrong command
DBUG_PRINT("info",("Command on %s = %d (%s)",
vio_description(net->vio), command,
- command_name[command]));
+ command_name[command].str));
}
net->read_timeout=old_timeout; // restore it
/*
@@ -1673,7 +1685,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB],
&LOCK_status);
thd->convert_string(&tmp, system_charset_info,
- packet, strlen(packet), thd->charset());
+ packet, packet_length-1, thd->charset());
if (!mysql_change_db(thd, tmp.str, FALSE))
{
general_log_print(thd, command, "%s",thd->db);
@@ -1691,7 +1703,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
case COM_TABLE_DUMP:
{
- char *db, *tbl_name;
+ char *tbl_name;
+ LEX_STRING db;
uint db_len= *(uchar*) packet;
if (db_len >= packet_length || db_len > NAME_LEN)
{
@@ -1707,34 +1720,41 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(thd->status_var.com_other, &LOCK_status);
thd->enable_slow_log= opt_log_slow_admin_statements;
- db= thd->alloc(db_len + tbl_len + 2);
- if (!db)
+ db.str= thd->alloc(db_len + tbl_len + 2);
+ db.length= db_len;
+ if (!db.str)
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
- tbl_name= strmake(db, packet + 1, db_len)+1;
+ tbl_name= strmake(db.str, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
- mysql_table_dump(thd, db, tbl_name);
+ mysql_table_dump(thd, &db, tbl_name);
break;
}
case COM_CHANGE_USER:
{
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
+ char *user= (char*) packet, *packet_end= packet+ packet_length;
+ char *passwd= strend(user)+1;
+
thd->change_user();
thd->clear_error(); // if errors from rollback
- statistic_increment(thd->status_var.com_other, &LOCK_status);
- char *user= (char*) packet;
- char *passwd= strend(user)+1;
/*
Old clients send null-terminated string ('\0' for empty string) for
password. New clients send the size (1 byte) + string (not null
terminated, so also '\0' for empty string).
*/
- char db_buff[NAME_LEN+1]; // buffer to store db in utf8
+ char db_buff[NAME_LEN+1]; // buffer to store db in utf8
char *db= passwd;
- uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- *passwd++ : strlen(passwd);
+ char *save_db;
+ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ *passwd++ : strlen(passwd));
+ uint dummy_errors, save_db_length, db_length, res;
+ Security_context save_security_ctx= *thd->security_ctx;
+ USER_CONN *save_user_connect;
+
db+= passwd_len + 1;
#ifndef EMBEDDED_LIBRARY
/* Small check for incoming packet */
@@ -1745,17 +1765,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
#endif
/* Convert database name to utf8 */
- uint dummy_errors;
+ /*
+ Handle problem with old bug in client protocol where db had an extra
+ \0
+ */
+ db_length= (packet_end - db);
+ if (db_length > 0 && db[db_length-1] == 0)
+ db_length--;
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info, db, strlen(db),
+ system_charset_info, db, db_length,
thd->charset(), &dummy_errors)]= 0;
db= db_buff;
/* Save user and privileges */
- uint save_db_length= thd->db_length;
- char *save_db= thd->db;
- Security_context save_security_ctx= *thd->security_ctx;
- USER_CONN *save_user_connect= thd->user_connect;
+ save_db_length= thd->db_length;
+ save_db= thd->db;
+ save_user_connect= thd->user_connect;
if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
{
@@ -1766,7 +1791,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Clear variables that are allocated */
thd->user_connect= 0;
- int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
+ res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
if (res)
{
@@ -1826,7 +1851,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query + thd->query_length;
- general_log_print(thd, command, "%.*b", thd->query_length, thd->query);
+ /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
+ const char *format= "%.*b";
+ general_log_print(thd, command, format, thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -1876,29 +1903,31 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
#else
{
- char *fields, *pend;
+ char *fields, *packet_end= packet + packet_length - 1, *arg_end;
/* Locked closure of all tables */
TABLE_LIST *locked_tables= NULL;
TABLE_LIST table_list;
LEX_STRING conv_name;
/* Saved variable value */
my_bool old_innodb_table_locks= thd->variables.innodb_table_locks;
-
+ uint dummy;
/* used as fields initializator */
lex_start(thd, 0, 0);
-
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
- if (thd->copy_db_to(&table_list.db, 0))
+ if (thd->copy_db_to(&table_list.db, &dummy))
break;
- pend= strend(packet);
+ /*
+ We have name + wildcard in packet, separated by endzero
+ */
+ arg_end= strend(packet);
thd->convert_string(&conv_name, system_charset_info,
- packet, (uint) (pend-packet), thd->charset());
+ packet, (uint) (arg_end - packet), thd->charset());
table_list.alias= table_list.table_name= conv_name.str;
- packet= pend+1;
+ packet= arg_end + 1;
if (!my_strcasecmp(system_charset_info, table_list.db,
information_schema_name.str))
@@ -1908,7 +1937,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
table_list.schema_table= schema_table;
}
- thd->query_length= strlen(packet); // for simplicity: don't optimize
+ thd->query_length= (uint) (packet_end - packet); // Don't count end \0
if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
break;
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
@@ -1944,24 +1973,27 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
error=TRUE; // End server
break;
+#ifdef REMOVED
case COM_CREATE_DB: // QQ: To be removed
{
- char *db=thd->strdup(packet), *alias;
+ LEX_STRING db, alias;
HA_CREATE_INFO create_info;
statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB],
&LOCK_status);
- // null test to handle EOM
- if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
+ if (thd->LEX_STRING_make(&db, packet, packet_length -1) ||
+ thd->LEX_STRING_make(&alias, db.str, db.length) ||
+ check_db_name(&db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
break;
}
- if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db)))
+ if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0,
+ is_schema_db(db.str)))
break;
general_log_print(thd, command, packet);
bzero(&create_info, sizeof(create_info));
- mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
+ mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str),
&create_info, 0);
break;
}
@@ -1969,14 +2001,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB],
&LOCK_status);
- char *db=thd->strdup(packet);
- /* null test to handle EOM */
- if (!db || check_db_name(db))
+ LEX_STRING db;
+
+ if (thd->LEX_STRING_make(&db, packet, packet_length - 1) ||
+ check_db_name(&db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
break;
}
- if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db)))
+ if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str)))
break;
if (thd->locked_tables || thd->active_transaction())
{
@@ -1984,10 +2017,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
break;
}
- general_log_print(thd, command, db);
- mysql_rm_db(thd, db, 0, 0);
+ general_log_print(thd, command, db.str);
+ mysql_rm_db(thd, db.str, 0, 0);
break;
}
+#endif
#ifndef EMBEDDED_LIBRARY
case COM_BINLOG_DUMP:
{
@@ -2069,37 +2103,47 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
case COM_STATISTICS:
{
- general_log_print(thd, command, NullS);
- statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS],
- &LOCK_status);
+ STATUS_VAR current_global_status_var;
+ ulong uptime;
+ uint length;
#ifndef EMBEDDED_LIBRARY
- char buff[200];
+ char buff[250];
+ uint buff_len= sizeof(buff);
#else
char *buff= thd->net.last_error;
+ uint buff_len= sizeof(thd->net.last_error);
#endif
- STATUS_VAR current_global_status_var;
+ general_log_print(thd, command, NullS);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS],
+ &LOCK_status);
calc_sum_of_all_status(&current_global_status_var);
-
- ulong uptime = (ulong) (thd->start_time - start_time);
- sprintf((char*) buff,
- "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f",
- uptime,
- (int) thread_count, (ulong) thd->query_id,
- current_global_status_var.long_query_count,
- current_global_status_var.opened_tables, refresh_version,
- cached_open_tables(),
- (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) :
- (double) 0));
+ uptime= (ulong) (thd->start_time - start_time);
+ length= my_snprintf((char*) buff, buff_len - 1,
+ "Uptime: %lu Threads: %d Questions: %lu "
+ "Slow queries: %lu Opens: %lu Flush tables: %lu "
+ "Open tables: %u Queries per second avg: %.3f",
+ uptime,
+ (int) thread_count, (ulong) thd->query_id,
+ current_global_status_var.long_query_count,
+ current_global_status_var.opened_tables,
+ refresh_version,
+ cached_open_tables(),
+ (uptime ? (ulonglong2double(thd->query_id) /
+ (double) uptime) : (double) 0));
#ifdef SAFEMALLOC
if (sf_malloc_cur_memory) // Using SAFEMALLOC
- sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK",
- (sf_malloc_cur_memory+1023L)/1024L,
- (sf_malloc_max_memory+1023L)/1024L);
+ {
+ char *end= buff + length;
+ length+= my_snprintf(end, buff_len - length - 1,
+ end," Memory in use: %ldK Max memory used: %ldK",
+ (sf_malloc_cur_memory+1023L)/1024L,
+ (sf_malloc_max_memory+1023L)/1024L);
+ }
#endif
#ifndef EMBEDDED_LIBRARY
- VOID(my_net_write(net, buff,(uint) strlen(buff)));
- VOID(net_flush(net));
+ VOID(my_net_write(net, buff, length));
+ VOID(net_flush(net));
#endif
break;
}
@@ -2296,26 +2340,28 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
DBUG_RETURN(1);
#else
{
- char *db;
+ LEX_STRING db;
+ uint dummy;
if (lex->select_lex.db == NULL &&
- thd->copy_db_to(&lex->select_lex.db, 0))
+ thd->copy_db_to(&lex->select_lex.db, &dummy))
{
DBUG_RETURN(1);
}
- db= lex->select_lex.db;
- if (check_db_name(db))
+ db.str= lex->select_lex.db;
+ db.length= strlen(db.str);
+ if (check_db_name(&db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db);
+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
DBUG_RETURN(1);
}
- if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0,
- is_schema_db(db)))
+ if (check_access(thd, SELECT_ACL, db.str, &thd->col_access, 0, 0,
+ is_schema_db(db.str)))
DBUG_RETURN(1); /* purecov: inspected */
- if (!thd->col_access && check_grant_db(thd,db))
+ if (!thd->col_access && check_grant_db(thd, db.str))
{
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
thd->security_ctx->priv_user, thd->security_ctx->priv_host,
- db);
+ db.str);
DBUG_RETURN(1);
}
break;
@@ -2550,7 +2596,23 @@ mysql_execute_command(THD *thd)
{
/* we warn the slave SQL thread */
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
- reset_one_shot_variables(thd);
+ if (thd->one_shot_set)
+ {
+ /*
+ It's ok to check thd->one_shot_set here:
+
+ The charsets in a MySQL 5.0 slave can change by both a binlogged
+ SET ONE_SHOT statement and the event-internal charset setting,
+ and these two ways to change charsets do not seems to work
+ together.
+
+ At least there seems to be problems in the rli cache for
+ charsets if we are using ONE_SHOT. Note that this is normally no
+ problem because either the >= 5.0 slave reads a 4.1 binlog (with
+ ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
+ */
+ reset_one_shot_variables(thd);
+ }
DBUG_RETURN(0);
}
}
@@ -2855,11 +2917,6 @@ mysql_execute_command(THD *thd)
if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
goto error;
}
- if (strlen(first_table->table_name) > NAME_LEN)
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name);
- break;
- }
pthread_mutex_lock(&LOCK_active_mi);
/*
fetch_master_table will send the error to the client on failure.
@@ -3089,11 +3146,6 @@ end_with_restore_list:
if (lex->alter_info.flags & ALTER_DROP_PARTITION)
priv_needed|= DROP_ACL;
- if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
- goto error;
- }
/* Must be set in the parser */
DBUG_ASSERT(select_lex->db);
if (check_access(thd, priv_needed, first_table->db,
@@ -3109,11 +3161,11 @@ end_with_restore_list:
{
if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
goto error;
- if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
+ if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
- tmp_table.table_name=lex->name;
+ tmp_table.table_name= lex->name.str;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
@@ -3141,7 +3193,7 @@ end_with_restore_list:
}
thd->enable_slow_log= opt_log_slow_admin_statements;
- res= mysql_alter_table(thd, select_lex->db, lex->name,
+ res= mysql_alter_table(thd, select_lex->db, lex->name.str,
&lex->create_info,
first_table, lex->create_list,
lex->key_list,
@@ -3753,9 +3805,10 @@ end_with_restore_list:
break;
}
char *alias;
- if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
+ if (!(alias=thd->strmake(lex->name.str, lex->name.length)) ||
+ check_db_name(&lex->name))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
break;
}
/*
@@ -3767,17 +3820,18 @@ end_with_restore_list:
*/
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
- (!rpl_filter->db_ok(lex->name) ||
- !rpl_filter->db_ok_with_wild_table(lex->name)))
+ (!rpl_filter->db_ok(lex->name.str) ||
+ !rpl_filter->db_ok_with_wild_table(lex->name.str)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
+ if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0,
+ is_schema_db(lex->name.str)))
break;
- res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
- &lex->create_info, 0);
+ res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
+ lex->name.str), &lex->create_info, 0);
break;
}
case SQLCOM_DROP_DB:
@@ -3787,9 +3841,9 @@ end_with_restore_list:
res= -1;
break;
}
- if (check_db_name(lex->name))
+ if (check_db_name(&lex->name))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
break;
}
/*
@@ -3801,14 +3855,15 @@ end_with_restore_list:
*/
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
- (!rpl_filter->db_ok(lex->name) ||
- !rpl_filter->db_ok_with_wild_table(lex->name)))
+ (!rpl_filter->db_ok(lex->name.str) ||
+ !rpl_filter->db_ok_with_wild_table(lex->name.str)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
+ if (check_access(thd,DROP_ACL,lex->name.str,0,1,0,
+ is_schema_db(lex->name.str)))
break;
if (thd->locked_tables || thd->active_transaction())
{
@@ -3816,7 +3871,7 @@ end_with_restore_list:
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
- res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0);
+ res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0);
break;
}
case SQLCOM_RENAME_DB:
@@ -3842,6 +3897,11 @@ end_with_restore_list:
break;
}
#endif
+ if (check_db_name(newdb))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), newdb->str);
+ break;
+ }
if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) ||
check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) ||
check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str)))
@@ -3863,11 +3923,10 @@ end_with_restore_list:
}
case SQLCOM_ALTER_DB:
{
- char *db= lex->name;
- DBUG_ASSERT(db); /* Must be set in the parser */
- if (!strip_sp(db) || check_db_name(db))
+ LEX_STRING *db= &lex->name;
+ if (check_db_name(db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db);
+ my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
break;
}
/*
@@ -3879,14 +3938,14 @@ end_with_restore_list:
*/
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
- (!rpl_filter->db_ok(db) ||
- !rpl_filter->db_ok_with_wild_table(db)))
+ (!rpl_filter->db_ok(db->str) ||
+ !rpl_filter->db_ok_with_wild_table(db->str)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db)))
+ if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)))
break;
if (thd->locked_tables || thd->active_transaction())
{
@@ -3894,21 +3953,22 @@ end_with_restore_list:
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
- res= mysql_alter_db(thd, db, &lex->create_info);
+ res= mysql_alter_db(thd, db->str, &lex->create_info);
break;
}
case SQLCOM_SHOW_CREATE_DB:
{
- if (!strip_sp(lex->name) || check_db_name(lex->name))
+ if (check_db_name(&lex->name))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
break;
}
- res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
+ res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info);
break;
}
case SQLCOM_CREATE_EVENT:
case SQLCOM_ALTER_EVENT:
+ do
{
DBUG_ASSERT(lex->event_parse_data);
if (lex->table_or_sp_used())
@@ -3934,16 +3994,15 @@ end_with_restore_list:
if (!res)
send_ok(thd);
- /* Don't do it, if we are inside a SP */
- if (!thd->spcont)
- {
- delete lex->sphead;
- lex->sphead= NULL;
- }
-
- /* lex->unit.cleanup() is called outside, no need to call it here */
- break;
+ } while (0);
+ /* Don't do it, if we are inside a SP */
+ if (!thd->spcont)
+ {
+ delete lex->sphead;
+ lex->sphead= NULL;
}
+ /* lex->unit.cleanup() is called outside, no need to call it here */
+ break;
case SQLCOM_DROP_EVENT:
case SQLCOM_SHOW_CREATE_EVENT:
{
@@ -6290,7 +6349,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
if (table->is_derived_table() == FALSE && table->db.str &&
- check_db_name(table->db.str))
+ check_db_name(&table->db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
DBUG_RETURN(0);
@@ -6319,7 +6378,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
- my_casedn_str(files_charset_info, table->table.str);
+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
@@ -7574,7 +7633,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
#ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT
/* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */
/*
- Only do the check for PS, becasue we on execute we have to check that
+ Only do the check for PS, because we on execute we have to check that
against the opened tables to ensure we don't use a table that is part
of the view (which can only be done after the table has been opened).
*/
diff --git a/sql/sql_parse.cc.rej b/sql/sql_parse.cc.rej
new file mode 100644
index 00000000000..6e2bd03867d
--- /dev/null
+++ b/sql/sql_parse.cc.rej
@@ -0,0 +1,166 @@
+***************
+*** 67,109 ****
+ static void decrease_user_connections(USER_CONN *uc);
+ #endif /* NO_EMBEDDED_ACCESS_CHECKS */
+ static bool check_multi_update_lock(THD *thd);
+- static void remove_escape(char *name);
+ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
+
+ const char *any_db="*any*"; // Special symbol for check_access
+
+! LEX_STRING command_name[]={
+! (char *)STRING_WITH_LEN("Sleep"),
+! (char *)STRING_WITH_LEN("Quit"),
+! (char *)STRING_WITH_LEN("Init DB"),
+! (char *)STRING_WITH_LEN("Query"),
+! (char *)STRING_WITH_LEN("Field List"),
+! (char *)STRING_WITH_LEN("Create DB"),
+! (char *)STRING_WITH_LEN("Drop DB"),
+! (char *)STRING_WITH_LEN("Refresh"),
+! (char *)STRING_WITH_LEN("Shutdown"),
+! (char *)STRING_WITH_LEN("Statistics"),
+! (char *)STRING_WITH_LEN("Processlist"),
+! (char *)STRING_WITH_LEN("Connect"),
+! (char *)STRING_WITH_LEN("Kill"),
+! (char *)STRING_WITH_LEN("Debug"),
+! (char *)STRING_WITH_LEN("Ping"),
+! (char *)STRING_WITH_LEN("Time"),
+! (char *)STRING_WITH_LEN("Delayed insert"),
+! (char *)STRING_WITH_LEN("Change user"),
+! (char *)STRING_WITH_LEN("Binlog Dump"),
+! (char *)STRING_WITH_LEN("Table Dump"),
+! (char *)STRING_WITH_LEN("Connect Out"),
+! (char *)STRING_WITH_LEN("Register Slave"),
+! (char *)STRING_WITH_LEN("Prepare"),
+! (char *)STRING_WITH_LEN("Execute"),
+! (char *)STRING_WITH_LEN("Long Data"),
+! (char *)STRING_WITH_LEN("Close stmt"),
+! (char *)STRING_WITH_LEN("Reset stmt"),
+! (char *)STRING_WITH_LEN("Set option"),
+! (char *)STRING_WITH_LEN("Fetch"),
+! (char *)STRING_WITH_LEN("Daemon"),
+! (char *)STRING_WITH_LEN("Error") // Last command number
+ };
+
+ const char *xa_state_names[]={
+--- 67,108 ----
+ static void decrease_user_connections(USER_CONN *uc);
+ #endif /* NO_EMBEDDED_ACCESS_CHECKS */
+ static bool check_multi_update_lock(THD *thd);
+ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
+
+ const char *any_db="*any*"; // Special symbol for check_access
+
+! const LEX_STRING command_name[]={
+! C_STRING_WITH_LEN("Sleep"),
+! C_STRING_WITH_LEN("Quit"),
+! C_STRING_WITH_LEN("Init DB"),
+! C_STRING_WITH_LEN("Query"),
+! C_STRING_WITH_LEN("Field List"),
+! C_STRING_WITH_LEN("Create DB"),
+! C_STRING_WITH_LEN("Drop DB"),
+! C_STRING_WITH_LEN("Refresh"),
+! C_STRING_WITH_LEN("Shutdown"),
+! C_STRING_WITH_LEN("Statistics"),
+! C_STRING_WITH_LEN("Processlist"),
+! C_STRING_WITH_LEN("Connect"),
+! C_STRING_WITH_LEN("Kill"),
+! C_STRING_WITH_LEN("Debug"),
+! C_STRING_WITH_LEN("Ping"),
+! C_STRING_WITH_LEN("Time"),
+! C_STRING_WITH_LEN("Delayed insert"),
+! C_STRING_WITH_LEN("Change user"),
+! C_STRING_WITH_LEN("Binlog Dump"),
+! C_STRING_WITH_LEN("Table Dump"),
+! C_STRING_WITH_LEN("Connect Out"),
+! C_STRING_WITH_LEN("Register Slave"),
+! C_STRING_WITH_LEN("Prepare"),
+! C_STRING_WITH_LEN("Execute"),
+! C_STRING_WITH_LEN("Long Data"),
+! C_STRING_WITH_LEN("Close stmt"),
+! C_STRING_WITH_LEN("Reset stmt"),
+! C_STRING_WITH_LEN("Set option"),
+! C_STRING_WITH_LEN("Fetch"),
+! C_STRING_WITH_LEN("Daemon"),
+! C_STRING_WITH_LEN("Error") // Last command number
+ };
+
+ const char *xa_state_names[]={
+***************
+*** 1738,1744 ****
+ password. New clients send the size (1 byte) + string (not null
+ terminated, so also '\0' for empty string).
+ */
+! char db_buff[NAME_LEN+1]; // buffer to store db in utf8
+ char *db= passwd;
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ *passwd++ : strlen(passwd);
+--- 1736,1742 ----
+ password. New clients send the size (1 byte) + string (not null
+ terminated, so also '\0' for empty string).
+ */
+! char db_buff[NAME_LEN+1]; // buffer to store db in utf8
+ char *db= passwd;
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ *passwd++ : strlen(passwd);
+***************
+*** 2315,2321 ****
+ DBUG_RETURN(1);
+ }
+ db= lex->select_lex.db;
+- remove_escape(db); // Fix escaped '_'
+ if (check_db_name(db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db);
+--- 2312,2317 ----
+ DBUG_RETURN(1);
+ }
+ db= lex->select_lex.db;
+ if (check_db_name(db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db);
+***************
+*** 6310,6345 ****
+ }
+
+
+- /* Fix escaping of _, % and \ in database and table names (for ODBC) */
+-
+- static void remove_escape(char *name)
+- {
+- if (!*name) // For empty DB names
+- return;
+- char *to;
+- #ifdef USE_MB
+- char *strend=name+(uint) strlen(name);
+- #endif
+- for (to=name; *name ; name++)
+- {
+- #ifdef USE_MB
+- int l;
+- if (use_mb(system_charset_info) &&
+- (l = my_ismbchar(system_charset_info, name, strend)))
+- {
+- while (l--)
+- *to++ = *name++;
+- name--;
+- continue;
+- }
+- #endif
+- if (*name == '\\' && name[1])
+- name++; // Skip '\\'
+- *to++= *name;
+- }
+- *to=0;
+- }
+-
+ /****************************************************************************
+ ** save order by and tables in own lists
+ ****************************************************************************/
+--- 6296,6301 ----
+ }
+
+
+ /****************************************************************************
+ ** save order by and tables in own lists
+ ****************************************************************************/
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 8df527fd25b..266a5bad34d 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4480,7 +4480,7 @@ that are reorganised.
{
if (!alt_part_info->use_default_partitions)
{
- DBUG_PRINT("info", ("part_info= %x", tab_part_info));
+ DBUG_PRINT("info", ("part_info: 0x%lx", (long) tab_part_info));
tab_part_info->use_default_partitions= FALSE;
}
tab_part_info->use_default_no_partitions= FALSE;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 013c3a17fd6..0c6a5fe5846 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1665,7 +1665,7 @@ static bool check_prepared_statement(Prepared_statement *stmt,
enum enum_sql_command sql_command= lex->sql_command;
int res= 0;
DBUG_ENTER("check_prepared_statement");
- DBUG_PRINT("enter",("command: %d, param_count: %ld",
+ DBUG_PRINT("enter",("command: %d, param_count: %u",
sql_command, stmt->param_count));
lex->first_lists_tables_same();
@@ -1916,9 +1916,12 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
thd->stmt_map.erase(stmt);
}
else
- general_log_print(thd, COM_STMT_PREPARE, "[%lu] %.*b", stmt->id,
+ {
+ const char *format= "[%lu] %.*b";
+ general_log_print(thd, COM_STMT_PREPARE, format, stmt->id,
stmt->query_length, stmt->query);
+ }
/* check_prepared_statemnt sends the metadata packet in case of success */
DBUG_VOID_RETURN;
}
@@ -2262,7 +2265,7 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
DBUG_VOID_RETURN;
DBUG_PRINT("exec_query", ("%s", stmt->query));
- DBUG_PRINT("info",("stmt: %p", stmt));
+ DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache);
@@ -2300,9 +2303,11 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
if (error == 0)
- general_log_print(thd, COM_STMT_EXECUTE, "[%lu] %.*b", stmt->id,
+ {
+ const char *format= "[%lu] %.*b";
+ general_log_print(thd, COM_STMT_EXECUTE, format, stmt->id,
thd->query_length, thd->query);
-
+ }
DBUG_VOID_RETURN;
set_params_data_err:
@@ -2355,7 +2360,7 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_VOID_RETURN;
}
- DBUG_PRINT("info",("stmt: %p", stmt));
+ DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
/*
If the free_list is not empty, we'll wrongly free some externally
@@ -2719,7 +2724,8 @@ void Prepared_statement::setup_set_params()
Prepared_statement::~Prepared_statement()
{
DBUG_ENTER("Prepared_statement::~Prepared_statement");
- DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor));
+ DBUG_PRINT("enter",("stmt: 0x%lx cursor: 0x%lx",
+ (long) this, (long) cursor));
delete cursor;
/*
We have to call free on the items even if cleanup is called as some items,
@@ -2740,7 +2746,7 @@ Query_arena::Type Prepared_statement::type() const
void Prepared_statement::cleanup_stmt()
{
DBUG_ENTER("Prepared_statement::cleanup_stmt");
- DBUG_PRINT("enter",("stmt: %p", this));
+ DBUG_PRINT("enter",("stmt: 0x%lx", (long) this));
/* The order is important */
lex->unit.cleanup();
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 52489087b02..d4f6288c298 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -431,6 +431,12 @@ impossible position";
goto err;
}
packet->set("\0", 1, &my_charset_bin);
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
+ this larger than the corresponding packet (query) sent
+ from client to master.
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
/*
We can set log_lock now, it does not move (it's a member of
@@ -805,7 +811,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
sizeof(mi->rli.until_log_name)-1);
}
else
- clear_until_condition(&mi->rli);
+ mi->rli.clear_until_condition();
if (mi->rli.until_condition != RELAY_LOG_INFO::UNTIL_NONE)
{
@@ -978,8 +984,8 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
Reset errors (the idea is that we forget about the
old master).
*/
- clear_slave_error(&mi->rli);
- clear_until_condition(&mi->rli);
+ mi->rli.clear_slave_error();
+ mi->rli.clear_until_condition();
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
end_master_info(mi);
@@ -1105,7 +1111,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
{
mi->master_log_pos= lex_mi->pos;
}
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
if (lex_mi->host)
strmake(mi->host, lex_mi->host, sizeof(mi->host)-1);
@@ -1222,7 +1228,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
}
}
mi->rli.group_master_log_pos = mi->master_log_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
/*
Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,
@@ -1244,8 +1250,8 @@ bool change_master(THD* thd, MASTER_INFO* mi)
pthread_mutex_lock(&mi->rli.data_lock);
mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */
/* Clear the errors, for a clean start */
- clear_slave_error(&mi->rli);
- clear_until_condition(&mi->rli);
+ mi->rli.clear_slave_error();
+ mi->rli.clear_until_condition();
/*
If we don't write new coordinates to disk now, then old will remain in
relay-log.info until START SLAVE is issued; but if mysqld is shutdown
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d40d9f16bb5..7ea8c6f4dfa 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8723,6 +8723,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->collation.collation);
else
new_field= item->make_string_field(table);
+ new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
@@ -8908,7 +8909,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
(make_copy_field ? 0 : copy_func),
modify_item, convert_blob_length);
case Item::TYPE_HOLDER:
- return ((Item_type_holder *)item)->make_field_by_type(table);
+ result= ((Item_type_holder *)item)->make_field_by_type(table);
+ result->set_derivation(item->collation.derivation);
+ return result;
default: // Dosen't have to be stored
return 0;
}
@@ -9488,7 +9491,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bool maybe_null=(*cur_group->item)->maybe_null;
key_part_info->null_bit=0;
key_part_info->field= field;
- key_part_info->offset= field->offset();
+ key_part_info->offset= field->offset(table->record[0]);
key_part_info->length= (uint16) field->key_length();
key_part_info->type= (uint8) field->key_type();
key_part_info->key_type =
@@ -9585,7 +9588,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
key_part_info->null_bit=0;
key_part_info->field= *reg_field;
- key_part_info->offset= (*reg_field)->offset();
+ key_part_info->offset= (*reg_field)->offset(table->record[0]);
key_part_info->length= (uint16) (*reg_field)->pack_length();
key_part_info->type= (uint8) (*reg_field)->key_type();
key_part_info->key_type =
@@ -10177,7 +10180,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (join->result->send_eof())
rc= 1; // Don't send error
}
- DBUG_PRINT("info",("%ld records output",join->send_records));
+ DBUG_PRINT("info",("%ld records output", (long) join->send_records));
}
else
rc= -1;
@@ -12557,8 +12560,9 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
DBUG_RETURN(0);
}
Field **first_field=entry->field+entry->s->fields - field_count;
- offset= field_count ?
- entry->field[entry->s->fields - field_count]->offset() : 0;
+ offset= (field_count ?
+ entry->field[entry->s->fields - field_count]->
+ offset(entry->record[0]) : 0);
reclength=entry->s->reclength-offset;
free_io_cache(entry); // Safety
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index f6e39fb7913..dc8946df876 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1058,6 +1058,9 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
else
packet->append(STRING_WITH_LEN("CREATE TABLE "));
+ if (create_info_arg &&
+ (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
+ packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
if (table_list->schema_table)
alias= table_list->schema_table->table_name;
else
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 6e4d3f2ed0a..29b53560067 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -844,6 +844,162 @@ outp:
}
+/*
+ copy a string,
+ with optional character set conversion,
+ with optional left padding (for binary -> UCS2 conversion)
+
+ SYNOPSIS
+ well_formed_copy_nhars()
+ to Store result here
+ to_length Maxinum length of "to" string
+ to_cs Character set of "to" string
+ from Copy from here
+ from_length Length of from string
+ from_cs From character set
+ nchars Copy not more that nchars characters
+ well_formed_error_pos Return position when "from" is not well formed
+ or NULL otherwise.
+ cannot_convert_error_pos Return position where a not convertable
+ character met, or NULL otherwise.
+ from_end_pos Return position where scanning of "from"
+ string stopped.
+ NOTES
+
+ RETURN
+ length of bytes copied to 'to'
+*/
+
+
+uint32
+well_formed_copy_nchars(CHARSET_INFO *to_cs,
+ char *to, uint to_length,
+ CHARSET_INFO *from_cs,
+ const char *from, uint from_length,
+ uint nchars,
+ const char **well_formed_error_pos,
+ const char **cannot_convert_error_pos,
+ const char **from_end_pos)
+{
+ uint res;
+
+ if ((to_cs == &my_charset_bin) ||
+ (from_cs == &my_charset_bin) ||
+ (to_cs == from_cs) ||
+ my_charset_same(from_cs, to_cs))
+ {
+ if (to_length < to_cs->mbminlen || !nchars)
+ {
+ *from_end_pos= from;
+ *cannot_convert_error_pos= NULL;
+ *well_formed_error_pos= NULL;
+ return 0;
+ }
+
+ if (to_cs == &my_charset_bin)
+ {
+ res= min(min(nchars, to_length), from_length);
+ memmove(to, from, res);
+ *from_end_pos= from + res;
+ *well_formed_error_pos= NULL;
+ *cannot_convert_error_pos= NULL;
+ }
+ else
+ {
+ int well_formed_error;
+ uint from_offset;
+
+ if ((from_offset= (from_length % to_cs->mbminlen)) &&
+ (from_cs == &my_charset_bin))
+ {
+ /*
+ Copying from BINARY to UCS2 needs to prepend zeros sometimes:
+ INSERT INTO t1 (ucs2_column) VALUES (0x01);
+ 0x01 -> 0x0001
+ */
+ uint pad_length= to_cs->mbminlen - from_offset;
+ bzero(to, pad_length);
+ memmove(to + pad_length, from, from_offset);
+ nchars--;
+ from+= from_offset;
+ from_length-= from_offset;
+ to+= to_cs->mbminlen;
+ to_length-= to_cs->mbminlen;
+ }
+
+ set_if_smaller(from_length, to_length);
+ res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
+ nchars, &well_formed_error);
+ memmove(to, from, res);
+ *from_end_pos= from + res;
+ *well_formed_error_pos= well_formed_error ? from + res : NULL;
+ *cannot_convert_error_pos= NULL;
+ if (from_offset)
+ res+= to_cs->mbminlen;
+ }
+ }
+ else
+ {
+ int cnvres;
+ my_wc_t wc;
+ int (*mb_wc)(struct charset_info_st *, my_wc_t *,
+ const uchar *, const uchar *)= from_cs->cset->mb_wc;
+ int (*wc_mb)(struct charset_info_st *, my_wc_t,
+ uchar *s, uchar *e)= to_cs->cset->wc_mb;
+ const uchar *from_end= (const uchar*) from + from_length;
+ uchar *to_end= (uchar*) to + to_length;
+ char *to_start= to;
+ *well_formed_error_pos= NULL;
+ *cannot_convert_error_pos= NULL;
+
+ for ( ; nchars; nchars--)
+ {
+ const char *from_prev= from;
+ if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ if (!*well_formed_error_pos)
+ *well_formed_error_pos= from;
+ from++;
+ wc= '?';
+ }
+ else if (cnvres > MY_CS_TOOSMALL)
+ {
+ /*
+ A correct multibyte sequence detected
+ But it doesn't have Unicode mapping.
+ */
+ if (!*cannot_convert_error_pos)
+ *cannot_convert_error_pos= from;
+ from+= (-cnvres);
+ wc= '?';
+ }
+ else
+ break; // Not enough characters
+
+outp:
+ if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ if (!*cannot_convert_error_pos)
+ *cannot_convert_error_pos= from_prev;
+ wc= '?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ *from_end_pos= from;
+ res= to - to_start;
+ }
+ return (uint32) res;
+}
+
+
+
+
void String::print(String *str)
{
char *st= (char*)Ptr, *end= st+str_length;
diff --git a/sql/sql_string.h b/sql/sql_string.h
index b1d417be2c2..a72b24ae9d0 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -30,6 +30,14 @@ String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs, uint *errors);
+uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs,
+ char *to, uint to_length,
+ CHARSET_INFO *from_cs,
+ const char *from, uint from_length,
+ uint nchars,
+ const char **well_formed_error_pos,
+ const char **cannot_convert_error_pos,
+ const char **from_end_pos);
class String
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 511d9fa6677..1f00275621a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3743,7 +3743,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
enum ha_extra_function function)
{
DBUG_ENTER("wait_while_table_is_used");
- DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %u",
+ DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu",
table->s->table_name.str, (ulong) table->s,
table->db_stat, table->s->version));
@@ -4631,7 +4631,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
DBUG_RETURN(TRUE);
}
- if (!src_db || check_db_name(src_db))
+ if (!src_db || check_db_name(&table_ident->db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL");
DBUG_RETURN(-1);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index c4c40ea63c8..219ca8260ed 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -248,14 +248,15 @@ print_plan(JOIN* join, uint idx, double record_count, double read_time,
if (join->best_read == DBL_MAX)
{
fprintf(DBUG_FILE,
- "%s; idx:%u, best: DBL_MAX, atime: %g, itime: %g, count: %g\n",
- info, idx, current_read_time, read_time, record_count);
+ "%s; idx: %u best: DBL_MAX atime: %g itime: %g count: %g\n",
+ info, idx, current_read_time, read_time, record_count);
}
else
{
fprintf(DBUG_FILE,
- "%s; idx:%u, best: %g, accumulated: %g, increment: %g, count: %g\n",
- info, idx, join->best_read, current_read_time, read_time, record_count);
+ "%s; idx :%u best: %g accumulated: %g increment: %g count: %g\n",
+ info, idx, join->best_read, current_read_time, read_time,
+ record_count);
}
/* Print the tables in JOIN->positions */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index fb56b7ae3b0..8baf84585b2 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1612,7 +1612,7 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
char *end)
{
DBUG_ENTER("Handle_old_incorrect_sql_modes_hook::process_unknown_string");
- DBUG_PRINT("info", ("unknown key:%60s", unknown_key));
+ DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end &&
unknown_key[INVALID_SQL_MODES_LENGTH] == '=' &&
@@ -1654,7 +1654,7 @@ process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root,
char *end)
{
DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string");
- DBUG_PRINT("info", ("unknown key:%60s", unknown_key));
+ DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
if (unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1 < end &&
unknown_key[INVALID_TRIGGER_TABLE_LENGTH] == '=' &&
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 1d119b99df0..2575f17d256 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -691,7 +691,7 @@ int mysql_update(THD *thd,
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
send_ok(thd, (ulong) thd->row_count_func, id, buff);
- DBUG_PRINT("info",("%d records updated",updated));
+ DBUG_PRINT("info",("%ld records updated", (long) updated));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
thd->abort_on_warning= 0;
@@ -788,7 +788,7 @@ static table_map get_table_map(List<Item> *items)
while ((item= (Item_field *) item_it++))
map|= item->used_tables();
- DBUG_PRINT("info",("table_map: 0x%08x", map));
+ DBUG_PRINT("info", ("table_map: 0x%08lx", (long) map));
return map;
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 5bf67af9271..98226c1651b 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1695,24 +1695,23 @@ mysql_rename_view(THD *thd,
const char *new_name,
TABLE_LIST *view)
{
- LEX_STRING pathstr, file;
+ LEX_STRING pathstr;
File_parser *parser;
- char view_path[FN_REFLEN];
+ char path_buff[FN_REFLEN];
bool error= TRUE;
DBUG_ENTER("mysql_rename_view");
- strxnmov(view_path, FN_REFLEN-1, mysql_data_home, "/", view->db, "/",
- view->table_name, reg_ext, NullS);
- (void) unpack_filename(view_path, view_path);
-
- pathstr.str= (char *)view_path;
- pathstr.length= strlen(view_path);
+ pathstr.str= (char *) path_buff;
+ pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
+ view->db, view->table_name,
+ reg_ext, 0);
if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) &&
is_equal(&view_type, parser->type()))
{
TABLE_LIST view_def;
- char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
+ char dir_buff[FN_REFLEN];
+ LEX_STRING dir, file;
/*
To be PS-friendly we should either to restore state of
@@ -1735,18 +1734,18 @@ mysql_rename_view(THD *thd,
view_def.revision - 1, num_view_backups))
goto err;
- strxnmov(dir_buff, FN_REFLEN-1, mysql_data_home, "/", view->db, "/",
- NullS);
- (void) unpack_filename(dir_buff, dir_buff);
+ dir.str= dir_buff;
+ dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1,
+ view->db, "", "", 0);
- pathstr.str= (char*)dir_buff;
- pathstr.length= strlen(dir_buff);
+ pathstr.str= path_buff;
+ pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
+ view->db, new_name, reg_ext, 0);
- file.str= file_buff;
- file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS)
- - file_buff);
+ file.str= pathstr.str + dir.length;
+ file.length= pathstr.length - dir.length;
- if (sql_create_definition_file(&pathstr, &file, view_file_type,
+ if (sql_create_definition_file(&dir, &file, view_file_type,
(gptr)&view_def, view_parameters,
num_view_backups))
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a439c859a6b..97881502686 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -746,7 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
- sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem
+ sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
%type <lex_str_ptr>
opt_table_alias
@@ -756,7 +756,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
- opt_constraint constraint ident_or_empty
+ opt_constraint constraint
%type <string>
text_string opt_gconcat_separator
@@ -1240,7 +1240,8 @@ create:
lex->create_info.options=$2 | $4;
lex->create_info.db_type= lex->thd->variables.table_type;
lex->create_info.default_table_charset= NULL;
- lex->name= 0;
+ lex->name.str= 0;
+ lex->name.length= 0;
lex->like_name= 0;
}
create2
@@ -1280,7 +1281,7 @@ create:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CREATE_DB;
- lex->name=$4.str;
+ lex->name= $4;
lex->create_info.options=$3;
}
| CREATE
@@ -1515,7 +1516,7 @@ clear_privileges:
sp_name:
ident '.' ident
{
- if (!$1.str || check_db_name($1.str))
+ if (!$1.str || check_db_name(&$1))
{
my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
YYABORT;
@@ -3148,7 +3149,7 @@ size_number:
uint text_shift_number= 0;
longlong prefix_number;
char *start_ptr= $1.str;
- uint str_len= strlen(start_ptr);
+ uint str_len= $1.length;
char *end_ptr= start_ptr + str_len;
int error;
prefix_number= my_strtoll10(start_ptr, &end_ptr, &error);
@@ -4672,7 +4673,8 @@ alter:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
- lex->name= 0;
+ lex->name.str= 0;
+ lex->name.length= 0;
lex->sql_command= SQLCOM_ALTER_TABLE;
lex->duplicates= DUP_ERROR;
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
@@ -4682,7 +4684,6 @@ alter:
lex->key_list.empty();
lex->col_list.empty();
lex->select_lex.init_order();
- lex->name= 0;
lex->like_name= 0;
lex->select_lex.db=
((TABLE_LIST*) lex->select_lex.table_list.first)->db;
@@ -4707,7 +4708,8 @@ alter:
THD *thd= Lex->thd;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name= $3;
- if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL))
+ if (lex->name.str == NULL &&
+ thd->copy_db_to(&lex->name.str, &lex->name.length))
YYABORT;
}
| ALTER PROCEDURE sp_name
@@ -4857,8 +4859,8 @@ opt_ev_sql_stmt: /* empty*/ { $$= 0;}
ident_or_empty:
- /* empty */ { $$= 0; }
- | ident { $$= $1.str; };
+ /* empty */ { $$.str= 0; $$.length= 0; }
+ | ident { $$= $1; };
alter_commands:
| DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
@@ -5136,19 +5138,20 @@ alter_list_item:
{
LEX *lex=Lex;
THD *thd= lex->thd;
+ uint dummy;
lex->select_lex.db=$3->db.str;
if (lex->select_lex.db == NULL &&
- thd->copy_db_to(&lex->select_lex.db, NULL))
+ thd->copy_db_to(&lex->select_lex.db, &dummy))
{
YYABORT;
}
if (check_table_name($3->table.str,$3->table.length) ||
- $3->db.str && check_db_name($3->db.str))
+ $3->db.str && check_db_name(&$3->db))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
YYABORT;
}
- lex->name= $3->table.str;
+ lex->name= $3->table;
lex->alter_info.flags|= ALTER_RENAME;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
@@ -7681,7 +7684,7 @@ drop:
LEX *lex=Lex;
lex->sql_command= SQLCOM_DROP_DB;
lex->drop_if_exists=$3;
- lex->name=$4.str;
+ lex->name= $4;
}
| DROP FUNCTION_SYM if_exists sp_name
{
@@ -8328,7 +8331,7 @@ show_param:
{
Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
Lex->create_info.options=$3;
- Lex->name=$4.str;
+ Lex->name= $4;
}
| CREATE TABLE_SYM table_ident
{
@@ -10333,7 +10336,8 @@ grant_ident:
{
LEX *lex= Lex;
THD *thd= lex->thd;
- if (thd->copy_db_to(&lex->current_select->db, NULL))
+ uint dummy;
+ if (thd->copy_db_to(&lex->current_select->db, &dummy))
YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index ef769a5b16e..2d2530eb876 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -150,7 +150,7 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
int pos;
const char *j;
DBUG_ENTER("find_type2");
- DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, typelib));
+ DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, (long) typelib));
if (!typelib->count)
{
diff --git a/sql/table.cc b/sql/table.cc
index 7f80b95c954..762206c7eb8 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -30,7 +30,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share,
uchar *head, File file);
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
uint types, char **names);
-static uint find_field(Field **fields, uint start, uint length);
+static uint find_field(Field **fields, byte *record, uint start, uint length);
/* Get column name from column hash */
@@ -1069,6 +1069,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
Field *field;
if (new_field_pack_flag <= 1)
key_part->fieldnr= (uint16) find_field(share->field,
+ share->default_values,
(uint) key_part->offset,
(uint) key_part->length);
if (!key_part->fieldnr)
@@ -1232,24 +1233,19 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (share->found_next_number_field)
{
- /*
- We must have a table object for find_ref_key to calculate field offset
- */
- TABLE tmp_table;
- tmp_table.record[0]= share->default_values;
-
reg_field= *share->found_next_number_field;
- reg_field->table= &tmp_table;
if ((int) (share->next_number_index= (uint)
- find_ref_key(share->key_info, share->keys, reg_field,
+ find_ref_key(share->key_info, share->keys,
+ share->default_values, reg_field,
&share->next_number_key_offset)) < 0)
{
+ /* Wrong field definition */
+ DBUG_ASSERT(0);
reg_field->unireg_check= Field::NONE; /* purecov: inspected */
share->found_next_number_field= 0;
}
else
reg_field->flags |= AUTO_INCREMENT_FLAG;
- reg_field->table= 0;
}
if (share->blob_fields)
@@ -1343,7 +1339,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
Field **field_ptr;
DBUG_ENTER("open_table_from_share");
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
- share->table_name.str, outparam));
+ share->table_name.str, (long) outparam));
error= 1;
bzero((char*) outparam, sizeof(*outparam));
@@ -1969,7 +1965,7 @@ TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
# field number +1
*/
-static uint find_field(Field **fields, uint start, uint length)
+static uint find_field(Field **fields, byte *record, uint start, uint length)
{
Field **field;
uint i, pos;
@@ -1977,7 +1973,7 @@ static uint find_field(Field **fields, uint start, uint length)
pos= 0;
for (field= fields, i=1 ; *field ; i++,field++)
{
- if ((*field)->offset() == start)
+ if ((*field)->offset(record) == start)
{
if ((*field)->key_length() == length)
return (i);
@@ -2258,7 +2254,7 @@ char *get_field(MEM_ROOT *mem, Field *field)
SYNPOSIS
check_db_name()
- name Name of database
+ org_name Name of database and length
NOTES
If lower_case_table_names is set then database is converted to lower case
@@ -2268,35 +2264,35 @@ char *get_field(MEM_ROOT *mem, Field *field)
1 error
*/
-bool check_db_name(char *name)
+bool check_db_name(LEX_STRING *org_name)
{
- char *start= name;
- /* Used to catch empty names and names with end space */
- bool last_char_is_space= TRUE;
+ char *name= org_name->str;
+
+ if (!org_name->length || org_name->length > NAME_LEN)
+ return 1;
if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
- while (*name)
- {
#if defined(USE_MB) && defined(USE_MB_IDENT)
- last_char_is_space= my_isspace(system_charset_info, *name);
- if (use_mb(system_charset_info))
+ if (use_mb(system_charset_info))
+ {
+ bool last_char_is_space= TRUE;
+ char *end= name + org_name->length;
+ while (name < end)
{
- int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
- if (len)
- {
- name += len;
- continue;
- }
+ int len;
+ last_char_is_space= my_isspace(system_charset_info, *name);
+ len= my_ismbchar(system_charset_info, name, end);
+ if (!len)
+ len= 1;
+ name+= len;
}
-#else
- last_char_is_space= *name==' ';
-#endif
- name++;
+ return last_char_is_space;
}
- return last_char_is_space || (uint) (name - start) > NAME_LEN;
+ else
+#endif
+ return org_name->str[org_name->length - 1] != ' '; /* purecov: inspected */
}
@@ -2405,8 +2401,8 @@ table_check_intact(TABLE *table, const uint table_f_count,
my_bool error= FALSE;
my_bool fields_diff_count;
DBUG_ENTER("table_check_intact");
- DBUG_PRINT("info",("table=%s expected_count=%d",table->alias, table_f_count));
- DBUG_PRINT("info",("last_create_time=%d", *last_create_time));
+ DBUG_PRINT("info",("table: %s expected_count: %d last_create_time: %ld",
+ table->alias, table_f_count, *last_create_time));
if ((fields_diff_count= (table->s->fields != table_f_count)) ||
(*last_create_time != table->file->stats.create_time))
diff --git a/sql/table.cc.rej b/sql/table.cc.rej
new file mode 100644
index 00000000000..fd728ba9965
--- /dev/null
+++ b/sql/table.cc.rej
@@ -0,0 +1,17 @@
+***************
+*** 2246,2252 ****
+
+ bool check_db_name(char *name)
+ {
+! char *start=name;
+ /* Used to catch empty names and names with end space */
+ bool last_char_is_space= TRUE;
+
+--- 2257,2263 ----
+
+ bool check_db_name(char *name)
+ {
+! char *start= name;
+ /* Used to catch empty names and names with end space */
+ bool last_char_is_space= TRUE;
+
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 3d9f278b3f7..6acf17520d9 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -961,13 +961,12 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
*/
if (shift)
{
- if (local_t > (TIMESTAMP_MAX_VALUE - shift*86400L +
- sp->revtis[i].rt_offset - saved_seconds))
+ if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift*86400L +
+ sp->revtis[i].rt_offset - saved_seconds))
{
DBUG_RETURN(0); /* my_time_t overflow */
}
- else
- local_t+= shift*86400L;
+ local_t+= shift*86400L;
}
if (sp->revtis[i].rt_type)
@@ -1744,8 +1743,8 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_leapcnt++;
DBUG_PRINT("info",
- ("time_zone_leap_second table: tz_leapcnt=%u tt_time=%lld offset=%ld",
- tz_leapcnt, (longlong)tz_lsis[tz_leapcnt-1].ls_trans,
+ ("time_zone_leap_second table: tz_leapcnt:%u tt_time: %lu offset: %ld",
+ tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans,
tz_lsis[tz_leapcnt-1].ls_corr));
res= table->file->index_next(table->record[0]);
@@ -2058,8 +2057,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
tz_info->timecnt++;
DBUG_PRINT("info",
- ("time_zone_transition table: tz_id=%u tt_time=%lld tt_id=%u",
- tzid, (longlong)ttime, ttid));
+ ("time_zone_transition table: tz_id: %u tt_time:%lu tt_id: %u",
+ tzid, (ulong) ttime, ttid));
res= table->file->index_next_same(table->record[0],
(byte*)table->field[0]->ptr, 4);
diff --git a/sql/unireg.cc b/sql/unireg.cc
index a20c59fd796..4514f969913 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -469,16 +469,16 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
int2store(pos+6, key->block_size);
pos+=8;
key_parts+=key->key_parts;
- DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx",
- key->flags,key->key_parts,
- key->key_part));
+ DBUG_PRINT("loop", ("flags: %d key_parts: %d at 0x%lx",
+ key->flags, key->key_parts,
+ (long) key->key_part));
for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
key_part != key_part_end ;
key_part++)
{
uint offset;
- DBUG_PRINT("loop",("field: %d startpos: %lu length: %ld",
+ DBUG_PRINT("loop",("field: %d startpos: %lu length: %d",
key_part->fieldnr, key_part->offset + data_offset,
key_part->length));
int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);