mirror of
https://github.com/MariaDB/server.git
synced 2025-09-18 04:07:41 +03:00
Manual merge from mysql-5.1.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
Use is subject to license terms.
|
||||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
@@ -89,6 +89,8 @@ So, we can read full search-structure as 32-bit word
|
||||
#include "mysql_version.h"
|
||||
#include "lex.h"
|
||||
|
||||
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
|
||||
|
||||
const char *default_dbug_option="d:t:o,/tmp/gen_lex_hash.trace";
|
||||
|
||||
struct my_option my_long_options[] =
|
||||
@@ -348,9 +350,7 @@ static void usage(int version)
|
||||
my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
|
||||
if (version)
|
||||
return;
|
||||
puts("Copyright (C) 2001 MySQL AB, by VVA and Monty");
|
||||
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
|
||||
and you are welcome to modify and redistribute it under the GPL license\n");
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
|
||||
puts("This program generates a perfect hashing function for the sql_lex.cc");
|
||||
printf("Usage: %s [OPTIONS]\n\n", my_progname);
|
||||
my_print_help(my_long_options);
|
||||
@@ -452,24 +452,9 @@ int main(int argc,char **argv)
|
||||
/* Broken up to indicate that it's not advice to you, gentle reader. */
|
||||
printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n");
|
||||
|
||||
printf("\
|
||||
/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.\n\
|
||||
\n\
|
||||
This program is free software; you can redistribute it and/or modify\n\
|
||||
it under the terms of the GNU General Public License as published by\n\
|
||||
the Free Software Foundation; version 2 of the License.\n\
|
||||
\n\
|
||||
This program is distributed in the hope that it will be useful,\n\
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
|
||||
GNU General Public License for more details.\n\
|
||||
\n\
|
||||
You should have received a copy of the GNU General Public License\n\
|
||||
along with this program; see the file COPYING. If not, write to the\n\
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston\n\
|
||||
MA 02110-1301 USA. */\n\
|
||||
\n\
|
||||
");
|
||||
puts("/*");
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
|
||||
puts("*/");
|
||||
|
||||
/* Broken up to indicate that it's not advice to you, gentle reader. */
|
||||
printf("/* Do " "not " "edit " "this " "file! This is generated by "
|
||||
|
@@ -2646,7 +2646,7 @@ String *Item_time_typecast::val_str(String *str)
|
||||
|
||||
bool Item_date_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
|
||||
{
|
||||
bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
|
||||
bool res= get_arg0_date(ltime, fuzzy_date);
|
||||
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
|
||||
ltime->time_type= MYSQL_TIMESTAMP_DATE;
|
||||
return res;
|
||||
|
163
sql/log_event.cc
163
sql/log_event.cc
@@ -59,6 +59,11 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd);
|
||||
|
||||
static const char *HA_ERR(int i)
|
||||
{
|
||||
/*
|
||||
This function should only be called in case of an error
|
||||
was detected
|
||||
*/
|
||||
DBUG_ASSERT(i != 0);
|
||||
switch (i) {
|
||||
case HA_ERR_KEY_NOT_FOUND: return "HA_ERR_KEY_NOT_FOUND";
|
||||
case HA_ERR_FOUND_DUPP_KEY: return "HA_ERR_FOUND_DUPP_KEY";
|
||||
@@ -111,7 +116,7 @@ static const char *HA_ERR(int i)
|
||||
case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
|
||||
case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
|
||||
}
|
||||
return 0;
|
||||
return "No Error!";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +137,7 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
|
||||
TABLE *table, const char * type,
|
||||
const char *log_name, ulong pos)
|
||||
{
|
||||
const char *handler_error= HA_ERR(ha_error);
|
||||
const char *handler_error= (ha_error ? HA_ERR(ha_error) : NULL);
|
||||
char buff[MAX_SLAVE_ERRMSG], *slider;
|
||||
const char *buff_end= buff + sizeof(buff);
|
||||
uint len;
|
||||
@@ -7596,7 +7601,8 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
|
||||
error= do_exec_row(rli);
|
||||
|
||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||
if (error)
|
||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||
DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
|
||||
|
||||
table->in_use = old_thd;
|
||||
@@ -8222,6 +8228,97 @@ Table_map_log_event::~Table_map_log_event()
|
||||
*/
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
|
||||
enum enum_tbl_map_status
|
||||
{
|
||||
/* no duplicate identifier found */
|
||||
OK_TO_PROCESS= 0,
|
||||
|
||||
/* this table map must be filtered out */
|
||||
FILTERED_OUT= 1,
|
||||
|
||||
/* identifier mapping table with different properties */
|
||||
SAME_ID_MAPPING_DIFFERENT_TABLE= 2,
|
||||
|
||||
/* a duplicate identifier was found mapping the same table */
|
||||
SAME_ID_MAPPING_SAME_TABLE= 3
|
||||
};
|
||||
|
||||
/*
|
||||
Checks if this table map event should be processed or not. First
|
||||
it checks the filtering rules, and then looks for duplicate identifiers
|
||||
in the existing list of rli->tables_to_lock.
|
||||
|
||||
It checks that there hasn't been any corruption by verifying that there
|
||||
are no duplicate entries with different properties.
|
||||
|
||||
In some cases, some binary logs could get corrupted, showing several
|
||||
tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
|
||||
early sanity check for such cases and avoid that the server crashes
|
||||
later.
|
||||
|
||||
In some corner cases, the master logs duplicate table map events, i.e.,
|
||||
same id, same database name, same table name (see: BUG#37137). This is
|
||||
different from the above as it's the same table that is mapped again
|
||||
to the same identifier. Thus we cannot just check for same ids and
|
||||
assume that the event is corrupted we need to check every property.
|
||||
|
||||
NOTE: in the event that BUG#37137 ever gets fixed, this extra check
|
||||
will still be valid because we would need to support old binary
|
||||
logs anyway.
|
||||
|
||||
@param rli The relay log info reference.
|
||||
@param table_list A list element containing the table to check against.
|
||||
@return OK_TO_PROCESS
|
||||
if there was no identifier already in rli->tables_to_lock
|
||||
|
||||
FILTERED_OUT
|
||||
if the event is filtered according to the filtering rules
|
||||
|
||||
SAME_ID_MAPPING_DIFFERENT_TABLE
|
||||
if the same identifier already maps a different table in
|
||||
rli->tables_to_lock
|
||||
|
||||
SAME_ID_MAPPING_SAME_TABLE
|
||||
if the same identifier already maps the same table in
|
||||
rli->tables_to_lock.
|
||||
*/
|
||||
static enum_tbl_map_status
|
||||
check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list)
|
||||
{
|
||||
DBUG_ENTER("check_table_map");
|
||||
enum_tbl_map_status res= OK_TO_PROCESS;
|
||||
|
||||
if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
|
||||
(!rpl_filter->db_ok(table_list->db) ||
|
||||
(rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
|
||||
res= FILTERED_OUT;
|
||||
else
|
||||
{
|
||||
for(RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(rli->tables_to_lock);
|
||||
ptr;
|
||||
ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_local))
|
||||
{
|
||||
if (ptr->table_id == table_list->table_id)
|
||||
{
|
||||
|
||||
if (strcmp(ptr->db, table_list->db) ||
|
||||
strcmp(ptr->alias, table_list->table_name) ||
|
||||
ptr->lock_type != TL_WRITE) // the ::do_apply_event always sets TL_WRITE
|
||||
res= SAME_ID_MAPPING_DIFFERENT_TABLE;
|
||||
else
|
||||
res= SAME_ID_MAPPING_SAME_TABLE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
|
||||
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
{
|
||||
RPL_TABLE_LIST *table_list;
|
||||
@@ -8248,20 +8345,13 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
table_list->alias= table_list->table_name = tname_mem;
|
||||
table_list->lock_type= TL_WRITE;
|
||||
table_list->next_global= table_list->next_local= 0;
|
||||
table_list->table_id= m_table_id;
|
||||
table_list->table_id= DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id);
|
||||
table_list->updating= 1;
|
||||
strmov(table_list->db, rpl_filter->get_rewrite_db(m_dbnam, &dummy_len));
|
||||
strmov(table_list->table_name, m_tblnam);
|
||||
|
||||
int error= 0;
|
||||
|
||||
if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
|
||||
(!rpl_filter->db_ok(table_list->db) ||
|
||||
(rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
|
||||
{
|
||||
my_free(memory, MYF(MY_WME));
|
||||
}
|
||||
else
|
||||
DBUG_PRINT("debug", ("table: %s is mapped to %u", table_list->table_name, table_list->table_id));
|
||||
enum_tbl_map_status tblmap_status= check_table_map(rli, table_list);
|
||||
if (tblmap_status == OK_TO_PROCESS)
|
||||
{
|
||||
DBUG_ASSERT(thd->lex->query_tables != table_list);
|
||||
|
||||
@@ -8290,8 +8380,48 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
const_cast<Relay_log_info*>(rli)->tables_to_lock_count++;
|
||||
/* 'memory' is freed in clear_tables_to_lock */
|
||||
}
|
||||
else // FILTERED_OUT, SAME_ID_MAPPING_*
|
||||
{
|
||||
/*
|
||||
If mapped already but with different properties, we raise an
|
||||
error.
|
||||
If mapped already but with same properties we skip the event.
|
||||
If filtered out we skip the event.
|
||||
|
||||
DBUG_RETURN(error);
|
||||
In all three cases, we need to free the memory previously
|
||||
allocated.
|
||||
*/
|
||||
if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE)
|
||||
{
|
||||
/*
|
||||
Something bad has happened. We need to stop the slave as strange things
|
||||
could happen if we proceed: slave crash, wrong table being updated, ...
|
||||
As a consequence we push an error in this case.
|
||||
*/
|
||||
|
||||
char buf[256];
|
||||
|
||||
my_snprintf(buf, sizeof(buf),
|
||||
"Found table map event mapping table id %u which "
|
||||
"was already mapped but with different settings.",
|
||||
table_list->table_id);
|
||||
|
||||
if (thd->slave_thread)
|
||||
rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
|
||||
ER(ER_SLAVE_FATAL_ERROR), buf);
|
||||
else
|
||||
/*
|
||||
For the cases in which a 'BINLOG' statement is set to
|
||||
execute in a user session
|
||||
*/
|
||||
my_printf_error(ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
|
||||
MYF(0), buf);
|
||||
}
|
||||
|
||||
my_free(memory, MYF(0));
|
||||
}
|
||||
|
||||
DBUG_RETURN(tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE);
|
||||
}
|
||||
|
||||
Log_event::enum_skip_reason
|
||||
@@ -9220,7 +9350,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
restart_rnd_next:
|
||||
error= table->file->rnd_next(table->record[0]);
|
||||
|
||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||
if (error)
|
||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||
switch (error) {
|
||||
|
||||
case 0:
|
||||
|
@@ -279,6 +279,8 @@ extern "C" sig_handler handle_segfault(int sig);
|
||||
|
||||
/* Constants */
|
||||
|
||||
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
|
||||
|
||||
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
|
||||
/*
|
||||
WARNING: When adding new SQL modes don't forget to update the
|
||||
@@ -7796,13 +7798,8 @@ static void usage(void)
|
||||
if (!default_collation_name)
|
||||
default_collation_name= (char*) default_charset_info->name;
|
||||
print_version();
|
||||
puts("\
|
||||
Copyright (C) 2000-2008 MySQL AB, by Monty and others.\n\
|
||||
Copyright (C) 2008 Sun Microsystems, Inc.\n\
|
||||
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
|
||||
and you are welcome to modify and redistribute it under the GPL license\n\n\
|
||||
Starts the MySQL database server.\n");
|
||||
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
|
||||
puts("Starts the MySQL database server.\n");
|
||||
printf("Usage: %s [OPTIONS]\n", my_progname);
|
||||
if (!opt_verbose)
|
||||
puts("\nFor more help options (several pages), use mysqld --verbose --help.");
|
||||
|
@@ -857,8 +857,8 @@ bool Protocol_text::store(const char *from, size_t length,
|
||||
{
|
||||
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
|
||||
#ifndef DBUG_OFF
|
||||
DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %s", field_pos,
|
||||
field_count, (length == 0? "" : from)));
|
||||
DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos,
|
||||
field_count, (int) length, (length == 0 ? "" : from)));
|
||||
DBUG_ASSERT(field_pos < field_count);
|
||||
DBUG_ASSERT(field_types == 0 ||
|
||||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
|
||||
|
@@ -7576,7 +7576,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
|
||||
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
|
||||
sum_func_list)
|
||||
item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
|
||||
thd->used_tables|= item->used_tables();
|
||||
thd->lex->used_tables|= item->used_tables();
|
||||
thd->lex->current_select->cur_pos_in_select_list++;
|
||||
}
|
||||
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
|
||||
@@ -7923,7 +7923,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
views and natural joins this update is performed inside the loop below.
|
||||
*/
|
||||
if (table)
|
||||
thd->used_tables|= table->map;
|
||||
thd->lex->used_tables|= table->map;
|
||||
|
||||
/*
|
||||
Initialize a generic field iterator for the current table reference.
|
||||
@@ -8008,7 +8008,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
field_table= nj_col->table_ref->table;
|
||||
if (field_table)
|
||||
{
|
||||
thd->used_tables|= field_table->map;
|
||||
thd->lex->used_tables|= field_table->map;
|
||||
field_table->covering_keys.intersect(field->part_of_key);
|
||||
field_table->merge_keys.merge(field->part_of_key);
|
||||
field_table->used_fields++;
|
||||
@@ -8016,7 +8016,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
}
|
||||
}
|
||||
else
|
||||
thd->used_tables|= item->used_tables();
|
||||
thd->lex->used_tables|= item->used_tables();
|
||||
thd->lex->current_select->cur_pos_in_select_list++;
|
||||
}
|
||||
/*
|
||||
|
@@ -649,7 +649,6 @@ THD::THD()
|
||||
is_slave_error= thread_specific_used= FALSE;
|
||||
hash_clear(&handler_tables_hash);
|
||||
tmp_table=0;
|
||||
used_tables=0;
|
||||
cuted_fields= sent_row_count= row_count= 0L;
|
||||
limit_found_rows= 0;
|
||||
row_count_func= -1;
|
||||
|
@@ -1734,13 +1734,6 @@ public:
|
||||
*/
|
||||
ha_rows examined_row_count;
|
||||
|
||||
/*
|
||||
The set of those tables whose fields are referenced in all subqueries
|
||||
of the query.
|
||||
TODO: possibly this it is incorrect to have used tables in THD because
|
||||
with more than one subquery, it is not clear what does the field mean.
|
||||
*/
|
||||
table_map used_tables;
|
||||
USER_CONN *user_connect;
|
||||
CHARSET_INFO *db_charset;
|
||||
/*
|
||||
|
@@ -631,7 +631,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
lock_type= table_list->lock_type;
|
||||
|
||||
thd_proc_info(thd, "init");
|
||||
thd->used_tables=0;
|
||||
thd->lex->used_tables=0;
|
||||
values= its++;
|
||||
value_count= values->elements;
|
||||
|
||||
@@ -779,7 +779,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd->used_tables) // Column used in values()
|
||||
if (thd->lex->used_tables) // Column used in values()
|
||||
restore_record(table,s->default_values); // Get empty record
|
||||
else
|
||||
{
|
||||
|
@@ -360,6 +360,7 @@ void lex_start(THD *thd)
|
||||
lex->server_options.port= -1;
|
||||
|
||||
lex->is_lex_started= TRUE;
|
||||
lex->used_tables= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@@ -1836,6 +1836,16 @@ typedef struct st_lex : public Query_tables_list
|
||||
uint create_select_pos;
|
||||
bool create_select_in_comment;
|
||||
|
||||
/*
|
||||
The set of those tables whose fields are referenced in all subqueries
|
||||
of the query.
|
||||
TODO: possibly this it is incorrect to have used tables in LEX because
|
||||
with subquery, it is not clear what does the field mean. To fix this
|
||||
we should aggregate used tables information for selected expressions
|
||||
into the select_lex.
|
||||
*/
|
||||
table_map used_tables;
|
||||
|
||||
st_lex();
|
||||
|
||||
virtual ~st_lex()
|
||||
|
@@ -1382,7 +1382,7 @@ static int mysql_test_select(Prepared_statement *stmt,
|
||||
if (open_normal_and_derived_tables(thd, tables, 0))
|
||||
goto error;
|
||||
|
||||
thd->used_tables= 0; // Updated by setup_fields
|
||||
thd->lex->used_tables= 0; // Updated by setup_fields
|
||||
|
||||
/*
|
||||
JOIN::prepare calls
|
||||
@@ -1551,7 +1551,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
|
||||
if (specific_prepare && (*specific_prepare)(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
thd->used_tables= 0; // Updated by setup_fields
|
||||
thd->lex->used_tables= 0; // Updated by setup_fields
|
||||
|
||||
/* Calls JOIN::prepare */
|
||||
DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option));
|
||||
|
@@ -406,7 +406,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
|
||||
|
||||
if (!ref->fixed && ref->fix_fields(thd, 0))
|
||||
return TRUE;
|
||||
thd->used_tables|= item->used_tables();
|
||||
thd->lex->used_tables|= item->used_tables();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1632,7 +1632,7 @@ JOIN::optimize()
|
||||
|
||||
if (exec_tmp_table1->distinct)
|
||||
{
|
||||
table_map used_tables= thd->used_tables;
|
||||
table_map used_tables= thd->lex->used_tables;
|
||||
JOIN_TAB *last_join_tab= join_tab+tables-1;
|
||||
do
|
||||
{
|
||||
@@ -2526,7 +2526,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
if (!(join= new JOIN(thd, fields, select_options, result)))
|
||||
DBUG_RETURN(TRUE);
|
||||
thd_proc_info(thd, "init");
|
||||
thd->used_tables=0; // Updated by setup_fields
|
||||
thd->lex->used_tables=0; // Updated by setup_fields
|
||||
err= join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit);
|
||||
@@ -16949,7 +16949,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
need_order=0;
|
||||
extra.append(STRING_WITH_LEN("; Using filesort"));
|
||||
}
|
||||
if (distinct & test_all_bits(used_tables,thd->used_tables))
|
||||
if (distinct & test_all_bits(used_tables, thd->lex->used_tables))
|
||||
extra.append(STRING_WITH_LEN("; Distinct"));
|
||||
|
||||
for (uint part= 0; part < tab->ref.key_parts; part++)
|
||||
|
Reference in New Issue
Block a user