Below is the list of changes that have just been committed into a local
5.1 repository of serg. When serg does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-03-16 14:09:30+01:00, serg@stripped +24 -0
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into janus.mylan:/usr/home/serg/Abk/mysql-5.1
MERGE: 1.2409.46.22
include/my_global.h@stripped, 2007-03-16 14:01:09+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.157.1.3
sql/ha_ndbcluster.cc@stripped, 2007-03-16 14:01:09+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.411.1.9
sql/ha_partition.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.83.1.3
sql/handler.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.295.1.3
sql/item_subselect.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.145.1.2
sql/log.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.253.4.3
sql/log_event.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.266.1.8
sql/mysql_priv.h@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.470.12.5
sql/opt_range.cc@stripped, 2007-03-16 14:01:10+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.264.1.1
sql/slave.cc@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.306.1.9
sql/slave.h@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.103.1.2
sql/sp.cc@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.138.1.1
sql/sql_acl.cc@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.228.1.3
sql/sql_insert.cc@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.246.1.11
sql/sql_select.cc@stripped, 2007-03-16 14:01:11+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.492.1.10
sql/sql_select.h@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.117.1.1
sql/sql_servers.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.5.1.1
sql/table.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.275.1.5
sql/table.h@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.158.1.8
sql/tztime.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.47.1.3
storage/heap/ha_heap.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.107.1.1
storage/innobase/handler/ha_innodb.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.320.1.3
storage/myisam/ha_myisam.cc@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.209.1.2
storage/myisammrg/ha_myisammrg.h@stripped, 2007-03-16 14:01:12+01:00, serg@stripped +0 -0
Auto merged
MERGE: 1.49.1.1
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: serg
# Host: janus.mylan
# Root: /usr/home/serg/Abk/mysql-5.1/RESYNC
--- 1.108/storage/heap/ha_heap.cc 2007-03-16 14:09:38 +01:00
+++ 1.109/storage/heap/ha_heap.cc 2007-03-16 14:09:38 +01:00
@@ -704,9 +704,10 @@
uint table_changes)
{
/* Check that auto_increment value was not changed */
- if ((table_changes != IS_EQUAL_YES &&
- info->used_fields & HA_CREATE_USED_AUTO) &&
- info->auto_increment_value != 0)
+ if ((info->used_fields & HA_CREATE_USED_AUTO &&
+ info->auto_increment_value != 0) ||
+ table_changes == IS_EQUAL_NO ||
+ table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
return COMPATIBLE_DATA_NO;
return COMPATIBLE_DATA_YES;
}
--- 1.211/storage/myisam/ha_myisam.cc 2007-03-16 14:09:38 +01:00
+++ 1.212/storage/myisam/ha_myisam.cc 2007-03-16 14:09:38 +01:00
@@ -320,6 +320,12 @@
RETURN VALUE
0 - Equal definitions.
1 - Different definitions.
+
+ TODO
+ - compare FULLTEXT keys;
+ - compare SPATIAL keys;
+ - compare FIELD_SKIP_ZERO which is converted to FIELD_NORMAL correctly
+ (should be corretly detected in table2myisam).
*/
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
@@ -345,6 +351,28 @@
{
HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
+ if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
+ continue;
+ else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
+ t2_keyinfo[i].flag & HA_FULLTEXT)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
+ test(t1_keyinfo[i].flag & HA_FULLTEXT),
+ test(t2_keyinfo[i].flag & HA_FULLTEXT)));
+ DBUG_RETURN(1);
+ }
+ if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
+ continue;
+ else if (t1_keyinfo[i].flag & HA_SPATIAL ||
+ t2_keyinfo[i].flag & HA_SPATIAL)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
+ test(t1_keyinfo[i].flag & HA_SPATIAL),
+ test(t2_keyinfo[i].flag & HA_SPATIAL)));
+ DBUG_RETURN(1);
+ }
if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
{
@@ -381,7 +409,14 @@
{
MI_COLUMNDEF *t1_rec= &t1_recinfo[i];
MI_COLUMNDEF *t2_rec= &t2_recinfo[i];
- if (t1_rec->type != t2_rec->type ||
+ /*
+ FIELD_SKIP_ZERO can be changed to FIELD_NORMAL in mi_create,
+ see NOTE1 in mi_create.c
+ */
+ if ((t1_rec->type != t2_rec->type &&
+ !(t1_rec->type == (int) FIELD_SKIP_ZERO &&
+ t1_rec->length == 1 &&
+ t2_rec->type == (int) FIELD_NORMAL)) ||
t1_rec->length != t2_rec->length ||
t1_rec->null_bit != t2_rec->null_bit)
{
--- 1.50/storage/myisammrg/ha_myisammrg.h 2007-03-16 14:09:38 +01:00
+++ 1.51/storage/myisammrg/ha_myisammrg.h 2007-03-16 14:09:38 +01:00
@@ -36,8 +36,8 @@
{
return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_NO_TRANSACTIONS |
HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED |
- HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE |
- HA_CAN_BIT_FIELD | HA_NO_COPY_ON_ALTER);
+ HA_ANY_INDEX_MAY_BE_UNIQUE | HA_CAN_BIT_FIELD |
+ HA_NO_COPY_ON_ALTER);
}
ulong index_flags(uint inx, uint part, bool all_parts) const
{
--- 1.297/sql/handler.cc 2007-03-16 14:09:38 +01:00
+++ 1.298/sql/handler.cc 2007-03-16 14:09:38 +01:00
@@ -2312,7 +2312,7 @@
}
-static bool update_frm_version(TABLE *table, bool needs_lock)
+static bool update_frm_version(TABLE *table)
{
char path[FN_REFLEN];
File file;
@@ -2324,9 +2324,6 @@
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
- if (needs_lock)
- pthread_mutex_lock(&LOCK_open);
-
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
{
uchar version[4];
@@ -2348,8 +2345,6 @@
err:
if (file >= 0)
VOID(my_close(file,MYF(MY_WME)));
- if (needs_lock)
- pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(result);
}
@@ -2466,7 +2461,7 @@
}
if ((error= check(thd, check_opt)))
return error;
- return update_frm_version(table, 0);
+ return update_frm_version(table);
}
@@ -2475,7 +2470,7 @@
int result;
if ((result= repair(thd, check_opt)))
return result;
- return update_frm_version(table, 0);
+ return update_frm_version(table);
}
@@ -3461,7 +3456,7 @@
{
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->no_replicate);
table->s->cached_row_logging_check= check;
}
--- 1.267/sql/log.cc 2007-03-16 14:09:38 +01:00
+++ 1.268/sql/log.cc 2007-03-16 14:09:38 +01:00
@@ -3773,7 +3773,7 @@
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
+ MyISAM or BDB) (table->next_number_keypart != 0), such event is
in fact not necessary. We could avoid logging it.
*/
Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
--- 1.268/sql/log_event.cc 2007-03-16 14:09:38 +01:00
+++ 1.269/sql/log_event.cc 2007-03-16 14:09:38 +01:00
@@ -1130,13 +1130,18 @@
char emit_buf[256];
int const bytes_written=
my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %-48.48s |%s|\n# ",
+ "# %8.8lx %-48.48s |%s|\n",
(unsigned long) (hexdump_from + (i & 0xfffffff0)),
hex_string, char_string);
DBUG_ASSERT(bytes_written >= 0);
DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf));
my_b_write(file, (byte*) emit_buf, bytes_written);
}
+ /*
+ need a # to prefix the rest of printouts for example those of
+ Rows_log_event::print_helper().
+ */
+ my_b_write(file, reinterpret_cast<const byte*>("# "), 2);
}
DBUG_VOID_RETURN;
}
@@ -1276,7 +1281,8 @@
1+4+ // code of autoinc and the 2 autoinc variables
1+6+ // code of charset and charset
1+1+MAX_TIME_ZONE_NAME_LENGTH+ // code of tz and tz length and tz name
- 1+2 // code of lc_time_names and lc_time_names_number
+ 1+2+ // code of lc_time_names and lc_time_names_number
+ 1+2 // code of charset_database and charset_database_number
], *start, *start_of_status;
ulong event_length;
@@ -1395,6 +1401,13 @@
int2store(start, lc_time_names_number);
start+= 2;
}
+ if (charset_database_number)
+ {
+ DBUG_ASSERT(charset_database_number <= 0xFFFF);
+ *start++= Q_CHARSET_DATABASE_CODE;
+ int2store(start, charset_database_number);
+ start+= 2;
+ }
/*
Here there could be code like
if (command-line-option-which-says-"log_this_variable" && inited)
@@ -1460,7 +1473,8 @@
sql_mode(thd_arg->variables.sql_mode),
auto_increment_increment(thd_arg->variables.auto_increment_increment),
auto_increment_offset(thd_arg->variables.auto_increment_offset),
- lc_time_names_number(thd_arg->variables.lc_time_names->number)
+ lc_time_names_number(thd_arg->variables.lc_time_names->number),
+ charset_database_number(0)
{
time_t end_time;
time(&end_time);
@@ -1468,6 +1482,9 @@
catalog_len = (catalog) ? (uint32) strlen(catalog) : 0;
/* status_vars_len is set just before writing the event */
db_len = (db) ? (uint32) strlen(db) : 0;
+ if (thd_arg->variables.collation_database != thd_arg->db_charset)
+ charset_database_number= thd_arg->variables.collation_database->number;
+
/*
If we don't use flags2 for anything else than options contained in
thd->options, it would be more efficient to flags2=thd_arg->options
@@ -1538,7 +1555,7 @@
db(NullS), catalog_len(0), status_vars_len(0),
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
auto_increment_increment(1), auto_increment_offset(1),
- time_zone_len(0), lc_time_names_number(0)
+ time_zone_len(0), lc_time_names_number(0), charset_database_number(0)
{
ulong data_len;
uint32 tmp;
@@ -1643,6 +1660,10 @@
lc_time_names_number= uint2korr(pos);
pos+= 2;
break;
+ case Q_CHARSET_DATABASE_CODE:
+ charset_database_number= uint2korr(pos);
+ pos+= 2;
+ break;
default:
/* That's why you must write status vars in growing order of code */
DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
@@ -1841,6 +1862,16 @@
lc_time_names_number, print_event_info->delimiter);
print_event_info->lc_time_names_number= lc_time_names_number;
}
+ if (charset_database_number != print_event_info->charset_database_number)
+ {
+ if (charset_database_number)
+ my_b_printf(file, "SET @@session.collation_database=%d%s\n",
+ charset_database_number, print_event_info->delimiter);
+ else
+ my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
+ print_event_info->delimiter);
+ print_event_info->charset_database_number= charset_database_number;
+ }
}
@@ -1996,7 +2027,21 @@
}
else
thd->variables.lc_time_names= &my_locale_en_US;
-
+ if (charset_database_number)
+ {
+ CHARSET_INFO *cs;
+ if (!(cs= get_charset(charset_database_number, MYF(0))))
+ {
+ char buf[20];
+ int10_to_str((int) charset_database_number, buf, -10);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
+ goto compare_errors;
+ }
+ thd->variables.collation_database= cs;
+ }
+ else
+ thd->variables.collation_database= thd->db_charset;
+
/* Execute the query (note that we bypass dispatch_command()) */
mysql_parse(thd, thd->query, thd->query_length);
@@ -2241,6 +2286,8 @@
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
ST_SERVER_VER_LEN);
+ // prevent overrun if log is corrupted on disk
+ server_version[ST_SERVER_VER_LEN-1]= 0;
created= uint4korr(buf+ST_CREATED_OFFSET);
/* We use log_pos to mark if this was an artificial event or not */
artificial_event= (log_pos == 0);
@@ -2364,6 +2411,8 @@
switch (binlog_ver) {
case 4: /* MySQL 5.0 */
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+ DBUG_EXECUTE_IF("pretend_version_50034_in_binlog",
+ strmov(server_version, "5.0.34"););
common_header_len= LOG_EVENT_HEADER_LEN;
number_of_event_types= LOG_EVENT_TYPES;
/* we'll catch my_malloc() error in is_valid() */
@@ -2454,6 +2503,7 @@
post_header_len= 0; /* will make is_valid() fail */
break;
}
+ calc_server_version_split();
}
@@ -2493,6 +2543,7 @@
post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
number_of_event_types*
sizeof(*post_header_len), MYF(0));
+ calc_server_version_split();
DBUG_VOID_RETURN;
}
@@ -2593,6 +2644,37 @@
}
#endif
+
+/**
+ Splits the event's 'server_version' string into three numeric pieces stored
+ into 'server_version_split':
+ X.Y.Zabc (X,Y,Z numbers, a not a digit) -> {X,Y,Z}
+ X.Yabc -> {X,Y,0}
+ Xabc -> {X,0,0}
+ 'server_version_split' is then used for lookups to find if the server which
+ created this event has some known bug.
+*/
+void Format_description_log_event::calc_server_version_split()
+{
+ char *p= server_version, *r;
+ ulong number;
+ for (uint i= 0; i<=2; i++)
+ {
+ number= strtoul(p, &r, 10);
+ server_version_split[i]= (uchar)number;
+ DBUG_ASSERT(number < 256); // fit in uchar
+ p= r;
+ DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice
+ if (*r == '.')
+ p++; // skip the dot
+ }
+ DBUG_PRINT("info",("Format_description_log_event::server_version_split:"
+ " '%s' %d %d %d", server_version,
+ server_version_split[0],
+ server_version_split[1], server_version_split[2]));
+}
+
+
/**************************************************************************
Load_log_event methods
General note about Load_log_event: the binlogging of LOAD DATA INFILE is
@@ -3253,8 +3335,8 @@
ex.skip_lines = skip_lines;
List<Item> field_list;
- thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
- set_fields(tables.db, field_list, &thd->main_lex.select_lex.context);
+ thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
+ set_fields(tables.db, field_list, &thd->lex->select_lex.context);
thd->variables.pseudo_thread_id= thread_id;
if (net)
{
@@ -5465,12 +5547,12 @@
DBUG_ASSERT(m_rows_cur <= m_rows_end);
/* The cast will always work since m_rows_cur <= m_rows_end */
- if (static_cast<my_size_t>(m_rows_end - m_rows_cur) < length)
+ if (static_cast<my_size_t>(m_rows_end - m_rows_cur) <= length)
{
my_size_t const block_size= 1024;
my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf;
my_ptrdiff_t const new_alloc=
- block_size * ((cur_size + length) / block_size + block_size - 1);
+ block_size * ((cur_size + length + block_size - 1) / block_size);
byte* const new_buf= (byte*)my_realloc((gptr)m_rows_buf, (uint) new_alloc,
MYF(MY_ALLOW_ZERO_PTR|MY_WME));
@@ -5491,7 +5573,7 @@
m_rows_end= m_rows_buf + new_alloc;
}
- DBUG_ASSERT(m_rows_cur + length < m_rows_end);
+ DBUG_ASSERT(m_rows_cur + length <= m_rows_end);
memcpy(m_rows_cur, row_data, length);
m_rows_cur+= length;
m_row_count++;
@@ -5741,10 +5823,10 @@
need to add code to assert that is the case.
*/
thd->binlog_flush_pending_rows_event(false);
- close_tables_for_reopen(thd, &rli->tables_to_lock);
+ TABLE_LIST *tables= rli->tables_to_lock;
+ close_tables_for_reopen(thd, &tables);
- if ((error= open_tables(thd, &rli->tables_to_lock,
- &rli->tables_to_lock_count, 0)))
+ if ((error= open_tables(thd, &tables, &rli->tables_to_lock_count, 0)))
{
if (thd->query_error || thd->is_fatal_error)
{
@@ -5763,15 +5845,45 @@
DBUG_RETURN(error);
}
}
+
+ /*
+ When the open and locking succeeded, we check all tables to
+ ensure that they still have the correct type.
+
+ We can use a down cast here since we know that every table added
+ to the tables_to_lock is a RPL_TABLE_LIST.
+ */
+
+ {
+ RPL_TABLE_LIST *ptr= rli->tables_to_lock;
+ for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global))
+ {
+ if (ptr->m_tabledef.compatible_with(rli, ptr->table))
+ {
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock= 0;
+ thd->query_error= 1;
+ rli->clear_tables_to_lock();
+ DBUG_RETURN(ERR_BAD_TABLE_DEF);
+ }
+ }
+ }
+
/*
- When the open and locking succeeded, we add all the tables to
- the table map and remove them from tables to lock.
+ ... and then we add all the tables to the table map and remove
+ them from tables to lock.
We also invalidate the query cache for all the tables, since
they will now be changed.
+
+ TODO [/Matz]: Maybe the query cache should not be invalidated
+ here? It might be that a table is not changed, even though it
+ was locked for the statement. We do know that each
+ Rows_log_event contain at least one row, so after processing one
+ Rows_log_event, we can invalidate the query cache for the
+ associated table.
*/
- TABLE_LIST *ptr;
- for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
+ for (TABLE_LIST *ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
{
rli->m_table_map.set_table(ptr->table_id, ptr->table);
}
@@ -6042,7 +6154,7 @@
{
bool const last_stmt_event= get_flags(STMT_END_F);
print_header(head, print_event_info, !last_stmt_event);
- my_b_printf(head, "\t%s: table id %lu", name, m_table_id);
+ my_b_printf(head, "\t%s: table id %lu\n", name, m_table_id);
print_base64(body, print_event_info, !last_stmt_event);
}
@@ -6224,11 +6336,11 @@
thd->query_id= next_query_id();
pthread_mutex_unlock(&LOCK_thread_count);
- TABLE_LIST *table_list;
+ RPL_TABLE_LIST *table_list;
char *db_mem, *tname_mem;
void *const memory=
my_multi_malloc(MYF(MY_WME),
- &table_list, sizeof(TABLE_LIST),
+ &table_list, sizeof(RPL_TABLE_LIST),
&db_mem, NAME_LEN + 1,
&tname_mem, NAME_LEN + 1,
NULL);
@@ -6274,11 +6386,27 @@
}
/*
- Open the table if it is not already open and add the table to table map.
- Note that for any table that should not be replicated, a filter is needed.
+ Open the table if it is not already open and add the table to
+ table map. Note that for any table that should not be
+ replicated, a filter is needed.
+
+ The creation of a new TABLE_LIST is used to up-cast the
+ table_list consisting of RPL_TABLE_LIST items. This will work
+ since the only case where the argument to open_tables() is
+ changed, is when thd->lex->query_tables == table_list, i.e.,
+ when the statement requires prelocking. Since this is not
+ executed when a statement is executed, this case will not occur.
+ As a precaution, an assertion is added to ensure that the bad
+ case is not a fact.
+
+ Either way, the memory in the list is *never* released
+ internally in the open_tables() function, hence we take a copy
+ of the pointer to make sure that it's not lost.
*/
uint count;
- if ((error= open_tables(thd, &table_list, &count, 0)))
+ DBUG_ASSERT(thd->lex->query_tables != table_list);
+ TABLE_LIST *tmp_table_list= table_list;
+ if ((error= open_tables(thd, &tmp_table_list, &count, 0)))
{
if (thd->query_error || thd->is_fatal_error)
{
@@ -6305,14 +6433,17 @@
*/
DBUG_ASSERT(m_table->in_use);
- table_def const def(m_coltype, m_colcnt);
- if (def.compatible_with(rli, m_table))
- {
- thd->query_error= 1;
- error= ERR_BAD_TABLE_DEF;
- goto err;
- /* purecov: end */
- }
+ /*
+ Use placement new to construct the table_def instance in the
+ memory allocated for it inside table_list.
+
+ The memory allocated by the table_def structure (i.e., not the
+ memory allocated *for* the table_def structure) is released
+ inside st_relay_log_info::clear_tables_to_lock() by calling the
+ table_def destructor explicitly.
+ */
+ new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt);
+ table_list->m_tabledef_valid= TRUE;
/*
We record in the slave's information that the table should be
--- 1.485/sql/mysql_priv.h 2007-03-16 14:09:38 +01:00
+++ 1.486/sql/mysql_priv.h 2007-03-16 14:09:38 +01:00
@@ -1492,7 +1492,7 @@
void mysql_print_status();
/* key.cc */
int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
- uint *key_length);
+ uint *key_length, uint *keypart);
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);
--- 1.265/sql/opt_range.cc 2007-03-16 14:09:38 +01:00
+++ 1.266/sql/opt_range.cc 2007-03-16 14:09:38 +01:00
@@ -8967,7 +8967,7 @@
if ((join->tables != 1) || /* The query must reference one table. */
((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
(!join->select_distinct)) ||
- (thd->lex->select_lex.olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
+ (join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
DBUG_RETURN(NULL);
if (table->s->keys == 0) /* There are no indexes to use. */
DBUG_RETURN(NULL);
--- 1.308/sql/slave.cc 2007-03-16 14:09:38 +01:00
+++ 1.309/sql/slave.cc 2007-03-16 14:09:38 +01:00
@@ -55,6 +55,7 @@
*/
int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
+int events_till_abort = -1;
typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
@@ -2207,11 +2208,16 @@
THD_CHECK_SENTRY(thd);
delete thd;
pthread_mutex_unlock(&LOCK_thread_count);
- mi->abort_slave = 0;
- mi->slave_running = 0;
- mi->io_thd = 0;
- pthread_mutex_unlock(&mi->run_lock);
+ mi->abort_slave= 0;
+ mi->slave_running= 0;
+ mi->io_thd= 0;
+ /*
+ Note: the order of the two following calls (first broadcast, then unlock)
+ is important. Otherwise a killer_thread can execute between the calls and
+ delete the mi structure leading to a crash! (see BUG#25306 for details)
+ */
pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
+ pthread_mutex_unlock(&mi->run_lock);
my_thread_end();
pthread_exit(0);
DBUG_RETURN(0); // Can't return anything here
@@ -2457,9 +2463,14 @@
THD_CHECK_SENTRY(thd);
delete thd;
pthread_mutex_unlock(&LOCK_thread_count);
+ /*
+ Note: the order of the broadcast and unlock calls below (first broadcast, then unlock)
+ is important. Otherwise a killer_thread can execute between the calls and
+ delete the mi structure leading to a crash! (see BUG#25306 for details)
+ */
pthread_cond_broadcast(&rli->stop_cond);
- // tell the world we are done
- pthread_mutex_unlock(&rli->run_lock);
+ pthread_mutex_unlock(&rli->run_lock); // tell the world we are done
+
my_thread_end();
pthread_exit(0);
DBUG_RETURN(0); // Can't return anything here
@@ -3654,6 +3665,70 @@
DBUG_VOID_RETURN;
}
+
+/**
+ Detects, based on master's version (as found in the relay log), if master
+ has a certain bug.
+ @param rli RELAY_LOG_INFO which tells the master's version
+ @param bug_id Number of the bug as found in bugs.mysql.com
+ @return TRUE if master has the bug, FALSE if it does not.
+*/
+bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id)
+{
+ struct st_version_range_for_one_bug {
+ uint bug_id;
+ const uchar introduced_in[3]; // first version with bug
+ const uchar fixed_in[3]; // first version with fix
+ };
+ static struct st_version_range_for_one_bug versions_for_all_bugs[]=
+ {
+ {24432, { 5, 0, 24 }, { 5, 0, 38 } },
+ {24432, { 5, 1, 12 }, { 5, 1, 17 } }
+ };
+ const uchar *master_ver=
+ rli->relay_log.description_event_for_exec->server_version_split;
+
+ DBUG_ASSERT(sizeof(rli->relay_log.description_event_for_exec->server_version_split) == 3);
+
+ for (uint i= 0;
+ i < sizeof(versions_for_all_bugs)/sizeof(*versions_for_all_bugs);i++)
+ {
+ const uchar *introduced_in= versions_for_all_bugs[i].introduced_in,
+ *fixed_in= versions_for_all_bugs[i].fixed_in;
+ if ((versions_for_all_bugs[i].bug_id == bug_id) &&
+ (memcmp(introduced_in, master_ver, 3) <= 0) &&
+ (memcmp(fixed_in, master_ver, 3) > 0))
+ {
+ // a short message for SHOW SLAVE STATUS (message length constraints)
+ my_printf_error(ER_UNKNOWN_ERROR, "master may suffer from"
+ " http://bugs.mysql.com/bug.php?id=%u"
+ " so slave stops; check error log on slave"
+ " for more info", MYF(0), bug_id);
+ // a verbose message for the error log
+ slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR,
+ "According to the master's version ('%s'),"
+ " it is probable that master suffers from this bug:"
+ " http://bugs.mysql.com/bug.php?id=%u"
+ " and thus replicating the current binary log event"
+ " may make the slave's data become different from the"
+ " master's data."
+ " To take no risk, slave refuses to replicate"
+ " this event and stops."
+ " We recommend that all updates be stopped on the"
+ " master and slave, that the data of both be"
+ " manually synchronized,"
+ " that master's binary logs be deleted,"
+ " that master be upgraded to a version at least"
+ " equal to '%d.%d.%d'. Then replication can be"
+ " restarted.",
+ rli->relay_log.description_event_for_exec->server_version,
+ bug_id,
+ fixed_in[0], fixed_in[1], fixed_in[2]);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List_iterator<i_string>;
--- 1.230/sql/sql_acl.cc 2007-03-16 14:09:38 +01:00
+++ 1.231/sql/sql_acl.cc 2007-03-16 14:09:39 +01:00
@@ -2994,6 +2994,13 @@
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
@@ -3211,6 +3218,13 @@
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql";
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
@@ -3350,6 +3364,13 @@
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql";
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
@@ -5394,6 +5415,13 @@
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_create_user");
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
/* CREATE USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
DBUG_RETURN(result != 1);
@@ -5466,6 +5494,13 @@
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_drop_user");
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
/* DROP USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
DBUG_RETURN(result != 1);
@@ -5530,6 +5565,13 @@
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_rename_user");
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
/* RENAME USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
DBUG_RETURN(result != 1);
@@ -5605,6 +5647,13 @@
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_revoke_all");
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
if ((result= open_grant_tables(thd, tables)))
DBUG_RETURN(result != 1);
@@ -5794,6 +5843,13 @@
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
/* Remove procedure access */
do
--- 1.249/sql/sql_insert.cc 2007-03-16 14:09:39 +01:00
+++ 1.250/sql/sql_insert.cc 2007-03-16 14:09:39 +01:00
@@ -59,6 +59,7 @@
#include "sql_trigger.h"
#include "sql_select.h"
#include "sql_show.h"
+#include "slave.h"
#ifndef EMBEDDED_LIBRARY
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
@@ -363,6 +364,7 @@
Name_resolution_context_state ctx_state;
#ifndef EMBEDDED_LIBRARY
char *query= thd->query;
+#endif
/*
log_on is about delayed inserts only.
By default, both logs are enabled (this won't cause problems if the server
@@ -370,7 +372,6 @@
*/
bool log_on= ((thd->options & OPTION_BIN_LOG) ||
(!(thd->security_ctx->master_access & SUPER_ACL)));
-#endif
thr_lock_type lock_type = table_list->lock_type;
Item *unused_conds= 0;
DBUG_ENTER("mysql_insert");
@@ -391,6 +392,36 @@
(duplic == DUP_UPDATE))
lock_type=TL_WRITE;
#endif
+ if ((lock_type == TL_WRITE_DELAYED) &&
+ (global_system_variables.binlog_format == BINLOG_FORMAT_STMT) &&
+ log_on && mysql_bin_log.is_open() &&
+ (values_list.elements > 1))
+ {
+ /*
+ Statement-based binary logging does not work in this case, because:
+ a) two concurrent statements may have their rows intermixed in the
+ queue, leading to autoincrement replication problems on slave (because
+ the values generated used for one statement don't depend only on the
+ value generated for the first row of this statement, so are not
+ replicable)
+ b) if first row of the statement has an error the full statement is
+ not binlogged, while next rows of the statement may be inserted.
+ c) if first row succeeds, statement is binlogged immediately with a
+ zero error code (i.e. "no error"), if then second row fails, query
+ will fail on slave too and slave will stop (wrongly believing that the
+ master got no error).
+ So we fallback to non-delayed INSERT.
+ Note that to be fully correct, we should test the "binlog format which
+ the delayed thread is going to use for this row". But in the common case
+ where the global binlog format is not changed and the session binlog
+ format may be changed, that is equal to the global binlog format.
+ We test it without mutex for speed reasons (condition rarely true), and
+ in the common case (global not changed) it is as good as without mutex;
+ if global value is changed, anyway there is uncertainty as the delayed
+ thread may be old and use the before-the-change value.
+ */
+ lock_type= TL_WRITE;
+ }
table_list->lock_type= lock_type;
#ifndef EMBEDDED_LIBRARY
@@ -505,6 +536,14 @@
thd->cuted_fields = 0L;
table->next_number_field=table->found_next_number_field;
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread &&
+ (info.handle_duplicates == DUP_UPDATE) &&
+ (table->next_number_field != NULL) &&
+ rpl_master_has_bug(&active_mi->rli, 24432))
+ goto abort;
+#endif
+
error=0;
thd->proc_info="update";
if (duplic != DUP_ERROR || ignore)
@@ -1024,7 +1063,7 @@
{
Item *fake_conds= 0;
TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, table_list, table_list->next_global)))
+ if ((duplicate= unique_table(thd, table_list, table_list->next_global, 1)))
{
update_non_unique_table_error(table_list, "INSERT", duplicate);
DBUG_RETURN(TRUE);
@@ -1193,14 +1232,13 @@
if (res == VIEW_CHECK_ERROR)
goto before_trg_err;
+ table->file->restore_auto_increment(prev_insert_id);
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])))
{
if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
{
- table->file->restore_auto_increment(prev_insert_id);
-
goto ok_or_after_trg_err;
}
goto err;
@@ -2536,7 +2574,7 @@
query
*/
if (!(lex->current_select->options & OPTION_BUFFER_RESULT) &&
- unique_table(thd, table_list, table_list->next_global))
+ unique_table(thd, table_list, table_list->next_global, 0))
{
/* Using same table for INSERT and SELECT */
lex->current_select->options|= OPTION_BUFFER_RESULT;
@@ -2557,6 +2595,15 @@
}
restore_record(table,s->default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
+
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread &&
+ (info.handle_duplicates == DUP_UPDATE) &&
+ (table->next_number_field != NULL) &&
+ rpl_master_has_bug(&active_mi->rli, 24432))
+ DBUG_RETURN(1);
+#endif
+
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -3160,8 +3207,7 @@
("Current statement %s row-based",
thd->current_stmt_binlog_row_based ? "is" : "is NOT"));
DBUG_PRINT("info",
- ("Current table (at 0x%lx) %s a temporary (or non-existing) "
- "table",
+ ("Current table (at 0x%lu) %s a temporary (or non-existant) table",
(ulong) table,
table && !table->s->tmp_table ? "is NOT" : "is"));
DBUG_PRINT("info",
--- 1.495/sql/sql_select.cc 2007-03-16 14:09:39 +01:00
+++ 1.496/sql/sql_select.cc 2007-03-16 14:09:39 +01:00
@@ -396,6 +396,7 @@
join_list= &select_lex->top_join_list;
union_part= (unit_arg->first_select()->next_select() != 0);
+ thd->lex->current_select->is_item_list_lookup= 1;
/*
If we have already executed SELECT, then it have not sense to prevent
its table from update (see unique_table())
@@ -455,6 +456,17 @@
select_lex->fix_prepare_information(thd, &conds, &having);
+ if (order)
+ {
+ ORDER *ord;
+ for (ord= order; ord; ord= ord->next)
+ {
+ Item *item= *ord->item;
+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+ item->split_sum_func(thd, ref_pointer_array, all_fields);
+ }
+ }
+
if (having && having->with_sum_func)
having->split_sum_func2(thd, ref_pointer_array, all_fields,
&having, TRUE);
@@ -738,7 +750,6 @@
}
{
- Item::cond_result having_value;
having= optimize_cond(this, having, join_list, &having_value);
if (thd->net.report_error)
{
@@ -746,6 +757,10 @@
DBUG_PRINT("error",("Error from optimize_cond"));
DBUG_RETURN(1);
}
+ if (select_lex->where)
+ select_lex->cond_value= cond_value;
+ if (select_lex->having)
+ select_lex->having_value= having_value;
if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
@@ -906,6 +921,7 @@
conds->update_used_tables();
DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
}
+
/*
Permorm the the optimization on fields evaluation mentioned above
for all on expressions.
@@ -7772,6 +7788,10 @@
break;
}
}
+ if (cond->type() == Item::COND_ITEM &&
+ !((Item_cond*)cond)->argument_list()->elements)
+ cond= new Item_int((int32)cond->val_bool());
+
}
else if (cond->type() == Item::FUNC_ITEM &&
((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
@@ -13411,7 +13431,7 @@
Item **select_item; /* The corresponding item from the SELECT clause. */
Field *from_field; /* The corresponding field from the FROM clause. */
uint counter;
- bool unaliased;
+ enum_resolution_type resolution;
/*
Local SP variables may be int but are expressions, not positions.
@@ -13434,7 +13454,7 @@
}
/* Lookup the current GROUP/ORDER field in the SELECT clause. */
select_item= find_item_in_list(order_item, fields, &counter,
- REPORT_EXCEPT_NOT_FOUND, &unaliased);
+ REPORT_EXCEPT_NOT_FOUND, &resolution);
if (!select_item)
return TRUE; /* The item is not unique, or some other error occured. */
@@ -13448,7 +13468,7 @@
original field name, we should additionaly check if we have conflict
for this name (in case if we would perform lookup in all tables).
*/
- if (unaliased && !order_item->fixed &&
+ if (resolution == RESOLVED_BEHIND_ALIAS && !order_item->fixed &&
order_item->fix_fields(thd, order->item))
return TRUE;
@@ -13518,16 +13538,11 @@
We check order_item->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called.
*/
- thd->lex->current_select->is_item_list_lookup= 1;
if (!order_item->fixed &&
(order_item->fix_fields(thd, order->item) ||
(order_item= *order->item)->check_cols(1) ||
thd->is_fatal_error))
- {
- thd->lex->current_select->is_item_list_lookup= 0;
return TRUE; /* Wrong field. */
- }
- thd->lex->current_select->is_item_list_lookup= 0;
uint el= all_fields.elements;
all_fields.push_front(order_item); /* Add new field to field list. */
@@ -13679,7 +13694,7 @@
{
Item **item;
uint counter;
- bool not_used;
+ enum_resolution_type not_used;
DBUG_ENTER("setup_new_fields");
thd->mark_used_columns= MARK_COLUMNS_READ; // Not really needed, but...
@@ -15639,10 +15654,13 @@
Item *cur_where= where;
if (join)
cur_where= join->conds;
- if (cur_where)
+ if (cur_where || cond_value != Item::COND_UNDEF)
{
str->append(STRING_WITH_LEN(" where "));
- cur_where->print(str);
+ if (cur_where)
+ cur_where->print(str);
+ else
+ str->append(cond_value != Item::COND_FALSE ? "1" : "0");
}
// group by & olap
@@ -15668,10 +15686,13 @@
if (join)
cur_having= join->having;
- if (cur_having)
+ if (cur_having || having_value != Item::COND_UNDEF)
{
str->append(STRING_WITH_LEN(" having "));
- cur_having->print(str);
+ if (cur_having)
+ cur_having->print(str);
+ else
+ str->append(having_value != Item::COND_FALSE ? "1" : "0");
}
if (order_list.elements)
--- 1.118/sql/sql_select.h 2007-03-16 14:09:39 +01:00
+++ 1.119/sql/sql_select.h 2007-03-16 14:09:39 +01:00
@@ -336,7 +336,7 @@
bool need_tmp, hidden_group_fields;
DYNAMIC_ARRAY keyuse;
- Item::cond_result cond_value;
+ Item::cond_result cond_value, having_value;
List<Item> all_fields; // to store all fields that used in query
//Above list changed to use temporary table
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
--- 1.277/sql/table.cc 2007-03-16 14:09:39 +01:00
+++ 1.278/sql/table.cc 2007-03-16 14:09:39 +01:00
@@ -120,7 +120,6 @@
share->normalized_path.length= path_length;
share->version= refresh_version;
- share->flush_version= flush_version;
/*
This constant is used to mark that no table map version has been
@@ -2915,7 +2914,9 @@
thd->net.last_errno == ER_SP_DOES_NOT_EXIST ||
thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
- thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR)
+ thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR ||
+ thd->net.last_errno == ER_TABLE_NOT_LOCKED ||
+ thd->net.last_errno == ER_NO_SUCH_TABLE)
{
TABLE_LIST *top= top_table();
thd->clear_error();
--- 1.160/sql/table.h 2007-03-16 14:09:39 +01:00
+++ 1.161/sql/table.h 2007-03-16 14:09:39 +01:00
@@ -168,7 +168,7 @@
ha_rows min_rows, max_rows; /* create information */
ulong avg_row_length; /* create information */
ulong raid_chunksize;
- ulong version, flush_version, mysql_version;
+ ulong version, mysql_version;
ulong timestamp_offset; /* Set to offset+1 of record */
ulong reclength; /* Recordlength */
@@ -409,6 +409,10 @@
/*
If true, the current table row is considered to have all columns set to
NULL, including columns declared as "not null" (see maybe_null).
+
+ TODO: Each of these flags take up 8 bits. They can just as easily
+ be put into one single unsigned long and instead of taking up 18
+ bytes, it would take up 4.
*/
my_bool null_row;
my_bool force_index;
@@ -416,6 +420,7 @@
my_bool key_read, no_keyread;
my_bool locked_by_flush;
my_bool locked_by_logger;
+ my_bool no_replicate;
my_bool locked_by_name;
my_bool fulltext_searched;
my_bool no_cache;
@@ -852,7 +857,7 @@
int view_check_option(THD *thd, bool ignore_failure);
bool setup_underlying(THD *thd);
void cleanup_items();
- bool placeholder() {return derived || view; }
+ bool placeholder() {return derived || view || schema_table || !table; }
void print(THD *thd, String *str);
bool check_single_table(st_table_list **table, table_map map,
st_table_list *view);
--- 1.149/sql/item_subselect.cc 2007-03-16 14:09:39 +01:00
+++ 1.150/sql/item_subselect.cc 2007-03-16 14:09:39 +01:00
@@ -2045,7 +2045,8 @@
table->file->ha_index_init(tab->ref.key, 0);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ tab_to_keypart_map(tab),
+ HA_READ_KEY_EXACT);
if (error &&
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
error= report_error(table, error);
@@ -2154,7 +2155,8 @@
table->file->ha_index_init(tab->ref.key, 1);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ tab_to_keypart_map(tab),
+ HA_READ_KEY_EXACT);
if (error &&
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
error= report_error(table, error);
--- 1.49/sql/tztime.cc 2007-03-16 14:09:39 +01:00
+++ 1.50/sql/tztime.cc 2007-03-16 14:09:39 +01:00
@@ -780,6 +780,8 @@
static my_time_t
sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
{
+ /* Guard against my_time_t overflow(on system with 32 bit my_time_t) */
+ DBUG_ASSERT(!(year == TIMESTAMP_MAX_YEAR && mon == 1 && mday > 17));
#ifndef WE_WANT_TO_HANDLE_UNORMALIZED_DATES
/*
It turns out that only whenever month is normalized or unnormalized
@@ -960,12 +962,12 @@
*/
if (shift)
{
- if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift*86400L +
+ if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift * SECS_PER_DAY +
sp->revtis[i].rt_offset - saved_seconds))
{
DBUG_RETURN(0); /* my_time_t overflow */
}
- local_t+= shift*86400L;
+ local_t+= shift * SECS_PER_DAY;
}
if (sp->revtis[i].rt_type)
@@ -1353,6 +1355,7 @@
Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
my_time_t local_t;
+ int shift= 0;
/*
Check timestamp range.we have to do this as calling function relies on
@@ -1361,9 +1364,23 @@
if (!validate_timestamp_range(t))
return 0;
- local_t= sec_since_epoch(t->year, t->month, t->day,
+ /*
+ Do a temporary shift of the boundary dates to avoid
+ overflow of my_time_t if the time value is near it's
+ maximum range
+ */
+ if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4)
+ shift= 2;
+
+ local_t= sec_since_epoch(t->year, t->month, (t->day - shift),
t->hour, t->minute, t->second) -
offset;
+
+ if (shift)
+ {
+ /* Add back the shifted time */
+ local_t+= shift * SECS_PER_DAY;
+ }
if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE)
return local_t;
--- 1.414/sql/ha_ndbcluster.cc 2007-03-16 14:09:39 +01:00
+++ 1.415/sql/ha_ndbcluster.cc 2007-03-16 14:09:39 +01:00
@@ -6143,9 +6143,16 @@
{
const NdbError err= dict->getNdbError();
if (err.code == 709 || err.code == 723)
+ {
error= -1;
+ DBUG_PRINT("info", ("ndb_error.code: %u", ndb_error.code));
+ }
else
+ {
+ error= -1;
ndb_error= err;
+ DBUG_PRINT("info", ("ndb_error.code: %u", ndb_error.code));
+ }
goto err;
}
DBUG_PRINT("info", ("Found table %s", tab->getName()));
@@ -8534,7 +8541,6 @@
goto ndb_util_thread_fail;
thd->init_for_queries();
thd->version=refresh_version;
- thd->set_time();
thd->main_security_ctx.host_or_ip= "";
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
--- 1.322/storage/innobase/handler/ha_innodb.cc 2007-03-16 14:09:39 +01:00
+++ 1.323/storage/innobase/handler/ha_innodb.cc 2007-03-16 14:09:39 +01:00
@@ -179,6 +179,7 @@
my_bool innobase_locks_unsafe_for_binlog = FALSE;
my_bool innobase_rollback_on_timeout = FALSE;
my_bool innobase_create_status_file = FALSE;
+my_bool innobase_stats_on_metadata = TRUE;
static char *internal_innobase_data_file_path = NULL;
@@ -1564,6 +1565,8 @@
srv_max_n_open_files = (ulint) innobase_open_files;
srv_innodb_status = (ibool) innobase_create_status_file;
+ srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
+
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
/* Store the default charset-collation number of this MySQL
@@ -5522,15 +5525,17 @@
ib_table = prebuilt->table;
if (flag & HA_STATUS_TIME) {
- /* In sql_show we call with this flag: update then statistics
- so that they are up-to-date */
+ if (srv_stats_on_metadata) {
+ /* In sql_show we call with this flag: update then statistics
+ so that they are up-to-date */
- prebuilt->trx->op_info = (char*)"updating table statistics";
+ prebuilt->trx->op_info = (char*)"updating table statistics";
- dict_update_statistics(ib_table);
+ dict_update_statistics(ib_table);
- prebuilt->trx->op_info = (char*)
- "returning various info to MySQL";
+ prebuilt->trx->op_info = (char*)
+ "returning various info to MySQL";
+ }
my_snprintf(path, sizeof(path), "%s/%s%s",
mysql_data_home, ib_table->name, reg_ext);
--- 1.159/include/my_global.h 2007-03-16 14:09:39 +01:00
+++ 1.160/include/my_global.h 2007-03-16 14:09:39 +01:00
@@ -1487,4 +1487,11 @@
#define dlerror() ""
#endif
+/*
+ Include standard definitions of operator new and delete.
+ */
+#ifdef __cplusplus
+#include <new>
+#endif
+
#endif /* my_global_h */
--- 1.85/sql/ha_partition.cc 2007-03-16 14:09:39 +01:00
+++ 1.86/sql/ha_partition.cc 2007-03-16 14:09:39 +01:00
@@ -4460,7 +4460,7 @@
2) It is called from close_thread_table which in turn is called from
close_thread_tables except in the case where the tables are locked
in which case ha_commit_stmt is called instead.
- It is only called from here if flush_version hasn't changed and the
+ It is only called from here if refresh_version hasn't changed and the
table is not an old table when calling close_thread_table.
close_thread_tables is called from many places as a general clean up
function after completing a query.
@@ -4481,8 +4481,9 @@
The handler will set HA_KEYREAD_ONLY in its table flags to indicate this
feature is supported.
HA_EXTRA_FLUSH:
- Indication to flush tables to disk, called at close_thread_table to
+ Indication to flush tables to disk, is supposed to be used to
ensure disk based tables are flushed at end of query execution.
+ Currently is never used.
2) Parameters used by some non-MyISAM handlers
----------------------------------------------
--- 1.6/sql/sql_servers.cc 2007-03-16 14:09:39 +01:00
+++ 1.7/sql/sql_servers.cc 2007-03-16 14:09:39 +01:00
@@ -545,6 +545,8 @@
DBUG_ENTER("insert_server_record");
table->use_all_columns();
+ empty_record(table);
+
/* set the field that's the PK to the value we're looking for */
table->field[0]->store(server->server_name,
server->server_name_length,
--- 1.139/sql/sp.cc 2007-03-16 14:09:39 +01:00
+++ 1.140/sql/sp.cc 2007-03-16 14:09:39 +01:00
@@ -497,6 +497,13 @@
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
sp->m_name.str));
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
if (!(table= open_proc_table_for_update(thd)))
ret= SP_OPEN_TABLE_FAILED;
else
@@ -633,6 +640,13 @@
DBUG_PRINT("enter", ("type: %d name: %.*s",
type, name->m_name.length, name->m_name.str));
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
+
if (!(table= open_proc_table_for_update(thd)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
@@ -664,6 +678,13 @@
DBUG_ENTER("db_update_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",
type, name->m_name.length, name->m_name.str));
+
+ /*
+ This statement will be replicated as a statement, even when using
+ row-based replication. The flag will be reset at the end of the
+ statement.
+ */
+ thd->clear_current_stmt_binlog_row_based();
if (!(table= open_proc_table_for_update(thd)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
| Thread |
|---|
| • bk commit into 5.1 tree (serg:1.2495) | Sergei Golubchik | 16 Mar |