Merge bodhi.local:/opt/local/work/tmp_merge

into  bodhi.local:/opt/local/work/mysql-5.1-runtime-merge-5.0


include/my_sys.h:
  Auto merged
mysql-test/r/auto_increment.result:
  Auto merged
mysql-test/r/func_math.result:
  Auto merged
mysql-test/r/func_system.result:
  Auto merged
mysql-test/r/func_time.result:
  Auto merged
mysql-test/r/information_schema.result:
  Auto merged
mysql-test/r/query_cache.result:
  Auto merged
mysql-test/r/subselect.result:
  Auto merged
mysql-test/r/trigger.result:
  Auto merged
mysql-test/r/type_blob.result:
  Auto merged
mysql-test/r/variables.result:
  Auto merged
mysql-test/r/view.result:
  Auto merged
mysql-test/t/trigger.test:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/log.cc:
  Auto merged
sql/slave.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_trigger.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp:
  Auto merged
storage/ndb/src/mgmsrv/ConfigInfo.cpp:
  Auto merged
sql/slave.h:
  SCCS merged
mysql-test/r/show_check.result:
  Manual merge.
mysql-test/t/show_check.test:
  Manual merge.
sql/log_event.cc:
  Manual merge.
sql/share/errmsg.txt:
  Manual merge.
sql/sql_class.h:
  Manual merge.
sql/sql_db.cc:
  Manual merge.
This commit is contained in:
unknown 2006-07-13 11:43:52 +04:00
commit d013f9e53a
26 changed files with 352 additions and 179 deletions

View file

@ -1693,14 +1693,33 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static const char *rewrite_db(const char *db)
{
if (replicate_rewrite_db.is_empty() || db == NULL)
return db;
I_List_iterator<i_string_pair> it(replicate_rewrite_db);
i_string_pair* tmp;
while ((tmp=it++))
{
if (strcmp(tmp->key, db) == 0)
return tmp->val;
}
return db;
}
int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
return exec_event(rli, query, q_len);
}
int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query_arg, uint32 q_len_arg)
int Query_log_event::exec_event(struct st_relay_log_info* rli,
const char *query_arg, uint32 q_len_arg)
{
LEX_STRING new_db;
int expected_error,actual_error= 0;
/*
Colleagues: please never free(thd->catalog) in MySQL. This would lead to
@ -1709,8 +1728,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
Thank you.
*/
thd->catalog= catalog_len ? (char *) catalog : (char *)"";
thd->db_length= db_len;
thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length); /* allocates a copy of 'db' */
thd->variables.auto_increment_increment= auto_increment_increment;
thd->variables.auto_increment_offset= auto_increment_offset;
@ -1929,7 +1949,7 @@ end:
TABLE uses the db.table syntax.
*/
thd->catalog= 0;
thd->reset_db(NULL, 0); // prevent db from being freed
thd->set_db(NULL, 0); /* will free the current database */
thd->query= 0; // just to be sure
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@ -2906,8 +2926,10 @@ void Load_log_event::set_fields(const char* affected_db,
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors)
{
thd->db_length= db_len;
thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
LEX_STRING new_db;
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length);
DBUG_ASSERT(thd->query == 0);
thd->query_length= 0; // Should not be needed
thd->query_error= 0;
@ -3110,7 +3132,7 @@ error:
const char *remember_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->catalog= 0;
thd->reset_db(NULL, 0);
thd->set_db(NULL, 0); /* will free the current database */
thd->query= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));

View file

@ -5594,6 +5594,8 @@ ER_NON_GROUPING_FIELD_USED 42000
eng "non-grouping field '%-.64s' is used in %-.64s clause"
ER_TABLE_CANT_HANDLE_SPKEYS
eng "The used table type doesn't support SPATIAL indexes"
ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
eng "Triggers can not be created on system tables"
ER_ILLEGAL_HA_CREATE_OPTION
eng "Table storage engine '%-.64s' does not support the create option '%.64s'"
ER_PARTITION_REQUIRES_VALUES_ERROR

View file

@ -1576,21 +1576,29 @@ public:
/*
Initialize the current database from a NULL-terminated string with length
If we run out of memory, we free the current database and return TRUE.
This way the user will notice the error as there will be no current
database selected (in addition to the error message set by malloc).
*/
void set_db(const char *new_db, uint new_db_len)
bool set_db(const char *new_db, uint new_db_len)
{
if (new_db)
/* Do not reallocate memory if current chunk is big enough. */
if (db && new_db && db_length >= new_db_len)
memcpy(db, new_db, new_db_len+1);
else
{
/* Do not reallocate memory if current chunk is big enough. */
if (db && db_length >= new_db_len)
memcpy(db, new_db, new_db_len+1);
else
{
safeFree(db);
db= my_strndup(new_db, new_db_len, MYF(MY_WME));
x_free(db);
db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
}
db_length= db ? new_db_len: 0;
}
db_length= db ? new_db_len : 0;
return new_db && !db;
}
void reset_db(char *new_db, uint new_db_len)
{

View file

@ -906,32 +906,13 @@ exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
error= Events::drop_schema_events(thd, db);
/*
If this database was the client's selected database, we silently change the
client's selected database to nothing (to have an empty SELECT DATABASE()
in the future). For this we free() thd->db and set it to 0. But we don't do
free() for the slave thread. Indeed, doing a x_free() on it leads to nasty
problems (i.e. long painful debugging) because in this thread, thd->db is
the same as data_buf and db of the Query_log_event which is dropping the
database. So if you free() thd->db, you're freeing data_buf. You set
thd->db to 0 but not data_buf (thd->db and data_buf are two distinct
pointers which point to the same place). Then in ~Query_log_event(), we
have 'if (data_buf) free(data_buf)' data_buf is !=0 so this makes a
DOUBLE free().
Side effects of this double free() are, randomly (depends on the machine),
when the slave is replicating a DROP DATABASE:
- garbage characters in the error message:
"Error 'Can't drop database 'test2'; database doesn't exist' on query
'h4zI<EFBFBD>©'"
- segfault
- hang in "free(vio)" (yes!) in the I/O or SQL slave threads (so slave
server hangs at shutdown etc).
If this database was the client's selected database, we silently
change the client's selected database to nothing (to have an empty
SELECT DATABASE() in the future). For this we free() thd->db and set
it to 0.
*/
if (thd->db && !strcmp(thd->db, db))
{
if (!(thd->slave_thread)) /* a slave thread will free it itself */
x_free(thd->db);
thd->reset_db(NULL, 0);
}
thd->set_db(NULL, 0);
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
exit2:
@ -1227,38 +1208,52 @@ err:
/*
Change default database.
Change the current database.
SYNOPSIS
mysql_change_db()
thd Thread handler
name Databasename
no_access_check True don't do access check. In this case name may be ""
thd thread handle
name database name
no_access_check if TRUE, don't do access check. In this
case name may be ""
DESCRIPTION
Becasue the database name may have been given directly from the
communication packet (in case of 'connect' or 'COM_INIT_DB')
we have to do end space removal in this function.
Check that the database name corresponds to a valid and
existent database, check access rights (unless called with
no_access_check), and set the current database. This function
is called to change the current database upon user request
(COM_CHANGE_DB command) or temporarily, to execute a stored
routine.
NOTES
Do as little as possible in this function, as it is not called for the
replication slave SQL thread (for that thread, setting of thd->db is done
in ::exec_event() methods of log_event.cc).
This function is not the only way to switch the database that
is currently employed. When the replication slave thread
switches the database before executing a query, it calls
thd->set_db directly. However, if the query, in turn, uses
a stored routine, the stored routine will use this function,
even if it's run on the slave.
This function does not send anything, including error messages to the
client, if that should be sent to the client, call net_send_error after
this function.
This function allocates the name of the database on the system
heap: this is necessary to be able to uniformly change the
database from any module of the server. Up to 5.0 different
modules were using different memory to store the name of the
database, and this led to memory corruption: a stack pointer
set by Stored Procedures was used by replication after the
stack address was long gone.
This function does not send anything, including error
messages, to the client. If that should be sent to the client,
call net_send_error after this function.
RETURN VALUES
0 ok
0 OK
1 error
*/
bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
{
int length, db_length;
char *dbname= thd->slave_thread ? (char *) name :
my_strdup((char *) name, MYF(MY_WME));
int path_length, db_length;
char *db_name;
char path[FN_REFLEN];
HA_CREATE_INFO create;
bool system_db= 0;
@ -1270,32 +1265,35 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
DBUG_ENTER("mysql_change_db");
DBUG_PRINT("enter",("name: '%s'",name));
LINT_INIT(db_length);
/* dbname can only be NULL if malloc failed */
if (!dbname || !(db_length= strlen(dbname)))
if (name == NULL || name[0] == '\0' && no_access_check == FALSE)
{
if (no_access_check && dbname)
{
/* Called from SP when orignal database was not set */
system_db= 1;
goto end;
}
if (!(thd->slave_thread))
x_free(dbname); /* purecov: inspected */
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
MYF(0)); /* purecov: inspected */
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
DBUG_RETURN(1); /* purecov: inspected */
}
if (check_db_name(dbname))
else if (name[0] == '\0')
{
my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
if (!(thd->slave_thread))
my_free(dbname, MYF(0));
/* 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;
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)
DBUG_RETURN(1); /* the error is set */
db_length= strlen(db_name);
if (check_db_name(db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name);
my_free(db_name, MYF(0));
DBUG_RETURN(1);
}
DBUG_PRINT("info",("Use database: %s", dbname));
if (!my_strcasecmp(system_charset_info, dbname, information_schema_name.str))
DBUG_PRINT("info",("Use database: %s", db_name));
if (!my_strcasecmp(system_charset_info, db_name, information_schema_name.str))
{
system_db= 1;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@ -1310,44 +1308,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, dbname, 0) |
db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name, 0) |
sctx->master_access);
if (!(db_access & DB_ACLS) && (!grant_option ||
check_grant_db(thd,dbname)))
check_grant_db(thd,db_name)))
{
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user,
sctx->priv_host,
dbname);
db_name);
general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR),
sctx->priv_user, sctx->priv_host, dbname);
if (!(thd->slave_thread))
my_free(dbname,MYF(0));
sctx->priv_user, sctx->priv_host, db_name);
my_free(db_name,MYF(0));
DBUG_RETURN(1);
}
}
#endif
length= build_table_filename(path, sizeof(path), dbname, "", "");
if (length && path[length-1] == FN_LIBCHAR)
path[length-1]=0; // remove ending '\'
path_length= build_table_filename(path, sizeof(path), db_name, "", "");
if (path_length && path[path_length-1] == FN_LIBCHAR)
path[path_length-1]= '\0'; // remove ending '\'
if (my_access(path,F_OK))
{
my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
if (!(thd->slave_thread))
my_free(dbname,MYF(0));
my_error(ER_BAD_DB_ERROR, MYF(0), db_name);
my_free(db_name, MYF(0));
DBUG_RETURN(1);
}
end:
if (!(thd->slave_thread))
x_free(thd->db);
if (dbname && dbname[0] == 0)
{
if (!(thd->slave_thread))
my_free(dbname, MYF(0));
thd->reset_db(NULL, 0);
}
else
thd->reset_db(dbname, db_length); // THD::~THD will free this
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
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!no_access_check)
sctx->db_access= db_access;

View file

@ -141,6 +141,7 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->select_lex.options= 0;
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();
lex->select_lex.group_list.empty();
lex->describe= 0;
@ -1070,6 +1071,7 @@ int MYSQLlex(void *arg, void *yythd)
void st_select_lex_node::init_query()
{
options= 0;
sql_cache= SQL_CACHE_UNSPECIFIED;
linkage= UNSPECIFIED_TYPE;
no_error= no_table_names_allowed= 0;
uncacheable= 0;
@ -1146,6 +1148,7 @@ void st_select_lex::init_select()
table_join_options= 0;
in_sum_expr= with_wild= 0;
options= 0;
sql_cache= SQL_CACHE_UNSPECIFIED;
braces= 0;
when_list.empty();
expr_list.empty();

View file

@ -338,6 +338,14 @@ protected:
public:
ulonglong options;
/*
In sql_cache we store SQL_CACHE flag as specified by user to be
able to restore SELECT statement from internal structures.
*/
enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE };
e_sql_cache sql_cache;
/*
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT

View file

@ -14584,10 +14584,19 @@ void st_select_lex::print(THD *thd, String *str)
str->append(STRING_WITH_LEN("sql_buffer_result "));
if (options & OPTION_FOUND_ROWS)
str->append(STRING_WITH_LEN("sql_calc_found_rows "));
if (!thd->lex->safe_to_cache_query)
str->append(STRING_WITH_LEN("sql_no_cache "));
if (options & OPTION_TO_QUERY_CACHE)
str->append(STRING_WITH_LEN("sql_cache "));
switch (sql_cache)
{
case SQL_NO_CACHE:
str->append(STRING_WITH_LEN("sql_no_cache "));
break;
case SQL_CACHE:
str->append(STRING_WITH_LEN("sql_cache "));
break;
case SQL_CACHE_UNSPECIFIED:
break;
default:
DBUG_ASSERT(0);
}
//Item List
bool first= 1;

View file

@ -183,6 +183,15 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
!(tables= add_table_for_trigger(thd, thd->lex->spname)))
DBUG_RETURN(TRUE);
/*
We don't allow creating triggers on tables in the 'mysql' schema
*/
if (create && !my_strcasecmp(system_charset_info, "mysql", tables->db))
{
my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0));
DBUG_RETURN(TRUE);
}
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
@ -372,7 +381,9 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
/* We don't allow creation of several triggers of the same type yet */
if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time])
{
my_message(ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS), MYF(0));
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"multiple triggers with the same action time"
" and event for one table");
return 1;
}

View file

@ -5707,10 +5707,21 @@ select_option:
YYABORT;
Select->options|= OPTION_FOUND_ROWS;
}
| SQL_NO_CACHE_SYM { Lex->safe_to_cache_query=0; }
| SQL_NO_CACHE_SYM
{
Lex->safe_to_cache_query=0;
Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
}
| SQL_CACHE_SYM
{
Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
/* Honor this flag only if SQL_NO_CACHE wasn't specified. */
if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE)
{
Lex->safe_to_cache_query=1;
Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
}
}
| ALL { Select->options|= SELECT_ALL; }
;
@ -8073,6 +8084,7 @@ truncate:
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
lex->select_lex.options= 0;
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();
}
;