1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-05 13:16:09 +03:00

Merge kpdesk.mysql.com:/home/thek/Development/cpp/mysql-5.1

into  kpdesk.mysql.com:/home/thek/Development/cpp/mysql-5.1-merge
This commit is contained in:
thek@kpdesk.mysql.com
2008-04-14 12:58:53 +02:00
21 changed files with 2118 additions and 4860 deletions

View File

@@ -1218,6 +1218,12 @@ DROP USER mysqltest_1@localhost;
DROP DATABASE db27878; DROP DATABASE db27878;
use test; use test;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#33275 Server crash when creating temporary table mysql.user
#
CREATE TEMPORARY TABLE mysql.user (id INT);
FLUSH PRIVILEGES;
DROP TABLE mysql.user;
drop table if exists test; drop table if exists test;
Warnings: Warnings:
Note 1051 Unknown table 'test' Note 1051 Unknown table 'test'

View File

@@ -249,4 +249,25 @@ set global slow_query_log_file= NULL;
ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL' ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL'
set global general_log_file= @old_general_log_file; set global general_log_file= @old_general_log_file;
set global slow_query_log_file= @old_slow_query_log_file; set global slow_query_log_file= @old_slow_query_log_file;
# --
# -- Bug#32748: Inconsistent handling of assignments to
# -- general_log_file/slow_query_log_file.
# --
SET @general_log_file_saved = @@global.general_log_file;
SET @slow_query_log_file_saved = @@global.slow_query_log_file;
SET GLOBAL general_log_file = 'bug32748.query.log';
SET GLOBAL slow_query_log_file = 'bug32748.slow.log';
SHOW VARIABLES LIKE '%log_file';
Variable_name Value
general_log_file bug32748.query.log
slow_query_log_file bug32748.slow.log
SET GLOBAL general_log_file = @general_log_file_saved;
SET GLOBAL slow_query_log_file = @slow_query_log_file_saved;
# -- End of Bug#32748.
End of 5.1 tests End of 5.1 tests

File diff suppressed because it is too large Load Diff

View File

@@ -1014,3 +1014,13 @@ Variable_name='table_lock_wait_timeout';
Variable_name Value Variable_name Value
table_definition_cache # table_definition_cache #
table_lock_wait_timeout # table_lock_wait_timeout #
# --
# -- Bug#34820: log_output can be set to illegal value.
# --
SET GLOBAL log_output = '';
ERROR 42000: Variable 'log_output' can't be set to the value of ''
SET GLOBAL log_output = 0;
ERROR 42000: Variable 'log_output' can't be set to the value of '0'
# -- End of Bug#34820.

View File

@@ -14,8 +14,8 @@ user_limits : Bug#23921 random failure of user_limits.test
concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences
federated_transactions : Bug#29523 Transactions do not work federated_transactions : Bug#29523 Transactions do not work
lowercase_table3 : Bug#32667 lowercase_table3.test reports to error log lowercase_table3 : Bug#32667 lowercase_table3.test reports to error log
innodb_mysql : Bug#32724: innodb_mysql.test fails randomly
ctype_create : Bug#32965 main.ctype_create fails ctype_create : Bug#32965 main.ctype_create fails
status : Bug#32966 main.status fails status : Bug#32966 main.status fails
ps_ddl : Bug#12093 2007-12-14 pending WL#4165 / WL#4166 ps_ddl : Bug#12093 2007-12-14 pending WL#4165 / WL#4166
csv_alter_table : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables csv_alter_table : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables
cast : Bug#35594 2008-03-27 main.cast fails on Windows2003-64

View File

@@ -1266,6 +1266,12 @@ DROP DATABASE db27878;
use test; use test;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#33275 Server crash when creating temporary table mysql.user
--echo #
CREATE TEMPORARY TABLE mysql.user (id INT);
FLUSH PRIVILEGES;
DROP TABLE mysql.user;
# #
# Bug #33201 Crash occurs when granting update privilege on one column of a view # Bug #33201 Crash occurs when granting update privilege on one column of a view
# #

View File

@@ -231,6 +231,34 @@ set global slow_query_log_file= NULL;
set global general_log_file= @old_general_log_file; set global general_log_file= @old_general_log_file;
set global slow_query_log_file= @old_slow_query_log_file; set global slow_query_log_file= @old_slow_query_log_file;
###########################################################################
--echo
--echo # --
--echo # -- Bug#32748: Inconsistent handling of assignments to
--echo # -- general_log_file/slow_query_log_file.
--echo # --
--echo
SET @general_log_file_saved = @@global.general_log_file;
SET @slow_query_log_file_saved = @@global.slow_query_log_file;
--echo
SET GLOBAL general_log_file = 'bug32748.query.log';
SET GLOBAL slow_query_log_file = 'bug32748.slow.log';
--echo
SHOW VARIABLES LIKE '%log_file';
--echo
SET GLOBAL general_log_file = @general_log_file_saved;
SET GLOBAL slow_query_log_file = @slow_query_log_file_saved;
--echo
--echo # -- End of Bug#32748.
###########################################################################
--echo End of 5.1 tests --echo End of 5.1 tests
--enable_ps_protocol --enable_ps_protocol

File diff suppressed because it is too large Load Diff

View File

@@ -778,3 +778,20 @@ set global thread_cache_size =@my_thread_cache_size;
--replace_column 2 # --replace_column 2 #
show global variables where Variable_name='table_definition_cache' or show global variables where Variable_name='table_definition_cache' or
Variable_name='table_lock_wait_timeout'; Variable_name='table_lock_wait_timeout';
###########################################################################
--echo
--echo # --
--echo # -- Bug#34820: log_output can be set to illegal value.
--echo # --
--error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL log_output = '';
--error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL log_output = 0;
--echo
--echo # -- End of Bug#34820.

View File

@@ -202,7 +202,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
{ {
if (mem_root->error_handler) if (mem_root->error_handler)
(*mem_root->error_handler)(); (*mem_root->error_handler)();
return((void*) 0); /* purecov: inspected */ DBUG_RETURN((void*) 0); /* purecov: inspected */
} }
mem_root->block_num++; mem_root->block_num++;
next->next= *prev; next->next= *prev;

View File

@@ -2314,9 +2314,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table deletes. table deletes.
*/ */
if ((thd->lex->sql_command != SQLCOM_DELETE)) if ((thd->lex->sql_command != SQLCOM_DELETE))
#ifdef NOT_USED
if ((thd->lex->sql_command != SQLCOM_UPDATE))
#endif
{ {
/* /*
Get best non-covering ROR-intersection plan and prepare data for Get best non-covering ROR-intersection plan and prepare data for

View File

@@ -1664,6 +1664,14 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
strmov(buff, "NULL"); strmov(buff, "NULL");
goto err; goto err;
} }
if (!m_allow_empty_value &&
res->length() == 0)
{
buff[0]= 0;
goto err;
}
var->save_result.ulong_value= ((ulong) var->save_result.ulong_value= ((ulong)
find_set(enum_names, res->c_ptr(), find_set(enum_names, res->c_ptr(),
res->length(), res->length(),
@@ -1679,10 +1687,19 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
else else
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->value->val_int();
/*
For when the enum is made to contain 64 elements, as 1ULL<<64 is if (!m_allow_empty_value &&
undefined, we guard with a "count<64" test. tmp == 0)
*/ {
buff[0]= '0';
buff[1]= 0;
goto err;
}
/*
For when the enum is made to contain 64 elements, as 1ULL<<64 is
undefined, we guard with a "count<64" test.
*/
if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) && if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) &&
(enum_names->count < 64))) (enum_names->count < 64)))
{ {
@@ -2382,32 +2399,51 @@ static int sys_check_log_path(THD *thd, set_var *var)
MY_STAT f_stat; MY_STAT f_stat;
String str(buff, sizeof(buff), system_charset_info), *res; String str(buff, sizeof(buff), system_charset_info), *res;
const char *log_file_str; const char *log_file_str;
size_t path_length;
if (!(res= var->value->val_str(&str))) if (!(res= var->value->val_str(&str)))
goto err; goto err;
log_file_str= res->c_ptr(); log_file_str= res->c_ptr();
bzero(&f_stat, sizeof(MY_STAT)); bzero(&f_stat, sizeof(MY_STAT));
(void) unpack_filename(path, log_file_str); path_length= unpack_filename(path, log_file_str);
if (!path_length)
{
/* File name is empty. */
goto err;
}
if (my_stat(path, &f_stat, MYF(0))) if (my_stat(path, &f_stat, MYF(0)))
{ {
/* Check if argument is a file and we have 'write' permission */ /*
A file system object exists. Check if argument is a file and we have
'write' permission.
*/
if (!MY_S_ISREG(f_stat.st_mode) || if (!MY_S_ISREG(f_stat.st_mode) ||
!(f_stat.st_mode & MY_S_IWRITE)) !(f_stat.st_mode & MY_S_IWRITE))
goto err; goto err;
return 0;
} }
else
{ /* Get dirname of the file path. */
size_t path_length; (void) dirname_part(path, log_file_str, &path_length);
/*
Check if directory exists and /* Dirname is empty if file path is relative. */
we have permission to create file & write to file if (!path_length)
*/ return 0;
(void) dirname_part(path, log_file_str, &path_length);
if (my_access(path, (F_OK|W_OK))) /*
goto err; Check if directory exists and we have permission to create file and
} write to file.
*/
if (my_access(path, (F_OK|W_OK)))
goto err;
return 0; return 0;
err: err:

View File

@@ -74,7 +74,8 @@ public:
sys_var(const char *name_arg, sys_after_update_func func= NULL, sys_var(const char *name_arg, sys_after_update_func func= NULL,
Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG)
:name(name_arg), after_update(func), no_support_one_shot(1), :name(name_arg), after_update(func), no_support_one_shot(1),
binlog_status(binlog_status_arg) binlog_status(binlog_status_arg),
m_allow_empty_value(TRUE)
{} {}
virtual ~sys_var() {} virtual ~sys_var() {}
void chain_sys_var(sys_var_chain *chain_arg) void chain_sys_var(sys_var_chain *chain_arg)
@@ -109,8 +110,16 @@ public:
virtual bool is_readonly() const { return 0; } virtual bool is_readonly() const { return 0; }
virtual sys_var_pluginvar *cast_pluginvar() { return 0; } virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
protected:
void set_allow_empty_value(bool allow_empty_value)
{
m_allow_empty_value= allow_empty_value;
}
private: private:
const Binlog_status_enum binlog_status; const Binlog_status_enum binlog_status;
bool m_allow_empty_value;
}; };
@@ -878,8 +887,11 @@ public:
sys_var_log_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg, sys_var_log_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg,
TYPELIB *typelib, sys_after_update_func func) TYPELIB *typelib, sys_after_update_func func)
:sys_var(name_arg,func), value(value_arg), enum_names(typelib) :sys_var(name_arg,func), value(value_arg), enum_names(typelib)
{ chain_sys_var(chain); } {
bool check(THD *thd, set_var *var) chain_sys_var(chain);
set_allow_empty_value(FALSE);
}
virtual bool check(THD *thd, set_var *var)
{ {
return check_set(thd, var, enum_names); return check_set(thd, var, enum_names);
} }

204
sql/sp.cc
View File

@@ -1070,210 +1070,6 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
} }
struct st_used_field
{
const char *field_name;
uint field_length;
enum enum_field_types field_type;
Field *field;
};
static struct st_used_field init_fields[]=
{
{ "Db", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
{ "Name", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
{ "Type", 9, MYSQL_TYPE_STRING, 0},
{ "Definer", USER_HOST_BUFF_SIZE, MYSQL_TYPE_STRING, 0},
{ "Modified", 0, MYSQL_TYPE_TIMESTAMP, 0},
{ "Created", 0, MYSQL_TYPE_TIMESTAMP, 0},
{ "Security_type", 1, MYSQL_TYPE_STRING, 0},
{ "Comment", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
{ "character_set_client", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
{ "collation_connection", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
{ "Database Collation", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
{ 0, 0, MYSQL_TYPE_STRING, 0}
};
static int
print_field_values(THD *thd, TABLE *table,
struct st_used_field *used_fields,
int type, const char *wild)
{
Protocol *protocol= thd->protocol;
if (table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == type)
{
String db_string;
String name_string;
struct st_used_field *used_field= used_fields;
if (get_field(thd->mem_root, used_field->field, &db_string))
db_string.set_ascii("", 0);
used_field+= 1;
get_field(thd->mem_root, used_field->field, &name_string);
if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
{
protocol->prepare_for_resend();
protocol->store(&db_string);
protocol->store(&name_string);
for (used_field++;
used_field->field_name;
used_field++)
{
switch (used_field->field_type) {
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME tmp_time;
bzero((char *)&tmp_time, sizeof(tmp_time));
((Field_timestamp *) used_field->field)->get_time(&tmp_time);
protocol->store(&tmp_time);
}
break;
default:
{
String tmp_string;
get_field(thd->mem_root, used_field->field, &tmp_string);
protocol->store(&tmp_string);
}
break;
}
}
if (protocol->write())
return SP_INTERNAL_ERROR;
}
}
return SP_OK;
}
/**
Implement SHOW STATUS statement for stored routines.
@param thd Thread context.
@param type Stored routine type
(TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION)
@param name_pattern Stored routine name pattern.
@return Error code. SP_OK is returned on success. Other SP_ constants are
used to indicate about errors.
*/
int
sp_show_status_routine(THD *thd, int type, const char *name_pattern)
{
TABLE *table;
TABLE_LIST tables;
int res;
DBUG_ENTER("sp_show_status_routine");
DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
type == TYPE_ENUM_FUNCTION);
memset(&tables, 0, sizeof(tables));
tables.db= (char*)"mysql";
tables.table_name= tables.alias= (char*)"proc";
if (! (table= open_ltable(thd, &tables, TL_READ, 0)))
{
res= SP_OPEN_TABLE_FAILED;
goto done;
}
else
{
Item *item;
List<Item> field_list;
struct st_used_field *used_field;
TABLE_LIST *leaves= 0;
st_used_field used_fields[array_elements(init_fields)];
table->use_all_columns();
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
/* Init header */
for (used_field= &used_fields[0];
used_field->field_name;
used_field++)
{
switch (used_field->field_type) {
case MYSQL_TYPE_TIMESTAMP:
item= new Item_return_date_time(used_field->field_name,
MYSQL_TYPE_DATETIME);
field_list.push_back(item);
break;
default:
item= new Item_empty_string(used_field->field_name,
used_field->field_length);
field_list.push_back(item);
break;
}
}
/* Print header */
if (thd->protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
{
res= SP_INTERNAL_ERROR;
goto err_case;
}
/*
Init fields
tables is not VIEW for sure => we can pass 0 as condition
*/
thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
setup_tables(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
&tables, &leaves, FALSE);
for (used_field= &used_fields[0];
used_field->field_name;
used_field++)
{
Item_field *field= new Item_field(&thd->lex->select_lex.context,
"mysql", "proc",
used_field->field_name);
if (!field ||
!(used_field->field= find_field_in_tables(thd, field, &tables, NULL,
0, REPORT_ALL_ERRORS, 1,
TRUE)))
{
res= SP_INTERNAL_ERROR;
goto err_case1;
}
}
table->file->ha_index_init(0, 1);
if ((res= table->file->index_first(table->record[0])))
{
res= (res == HA_ERR_END_OF_FILE) ? 0 : SP_INTERNAL_ERROR;
goto err_case1;
}
do
{
res= print_field_values(thd, table, used_fields, type, name_pattern);
if (res)
goto err_case1;
}
while (!table->file->index_next(table->record[0]));
res= SP_OK;
}
err_case1:
my_eof(thd);
err_case:
table->file->ha_index_end();
close_thread_tables(thd);
done:
DBUG_RETURN(res);
}
/** /**
Drop all routines in database 'db' Drop all routines in database 'db'

View File

@@ -48,9 +48,6 @@ sp_routine_exists_in_table(THD *thd, int type, sp_name *name);
bool bool
sp_show_create_routine(THD *thd, int type, sp_name *name); sp_show_create_routine(THD *thd, int type, sp_name *name);
int
sp_show_status_routine(THD *thd, int type, const char *wild);
int int
sp_create_routine(THD *thd, int type, sp_head *sp); sp_create_routine(THD *thd, int type, sp_head *sp);

View File

@@ -695,6 +695,8 @@ my_bool acl_reload(THD *thd)
tables[0].next_local= tables[0].next_global= tables+1; tables[0].next_local= tables[0].next_global= tables+1;
tables[1].next_local= tables[1].next_global= tables+2; tables[1].next_local= tables[1].next_global= tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
tables[0].skip_temporary= tables[1].skip_temporary=
tables[2].skip_temporary= TRUE;
if (simple_open_n_lock_tables(thd, tables)) if (simple_open_n_lock_tables(thd, tables))
{ {
@@ -3537,7 +3539,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
THR_MALLOC); THR_MALLOC);
DBUG_ENTER("grant_load"); DBUG_ENTER("grant_load_procs_priv");
(void) hash_init(&proc_priv_hash,system_charset_info, (void) hash_init(&proc_priv_hash,system_charset_info,
0,0,0, (hash_get_key) get_grant_table, 0,0,0, (hash_get_key) get_grant_table,
0,0); 0,0);
@@ -3721,6 +3723,7 @@ static my_bool grant_reload_procs_priv(THD *thd)
table.alias= table.table_name= (char*) "procs_priv"; table.alias= table.table_name= (char*) "procs_priv";
table.db= (char *) "mysql"; table.db= (char *) "mysql";
table.lock_type= TL_READ; table.lock_type= TL_READ;
table.skip_temporary= 1;
if (simple_open_n_lock_tables(thd, &table)) if (simple_open_n_lock_tables(thd, &table))
{ {
@@ -3786,7 +3789,7 @@ my_bool grant_reload(THD *thd)
tables[0].db= tables[1].db= (char *) "mysql"; tables[0].db= tables[1].db= (char *) "mysql";
tables[0].next_local= tables[0].next_global= tables+1; tables[0].next_local= tables[0].next_global= tables+1;
tables[0].lock_type= tables[1].lock_type= TL_READ; tables[0].lock_type= tables[1].lock_type= TL_READ;
tables[0].skip_temporary= tables[1].skip_temporary= TRUE;
/* /*
To avoid deadlocks we should obtain table locks before To avoid deadlocks we should obtain table locks before
obtaining LOCK_grant rwlock. obtaining LOCK_grant rwlock.

View File

@@ -345,26 +345,9 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (!(share= alloc_table_share(table_list, key, key_length))) if (!(share= alloc_table_share(table_list, key, key_length)))
{ {
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
DBUG_RETURN(0); DBUG_RETURN(0);
} }
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
// We need a write lock to be able to add a new entry
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&LOCK_open);
/* Check that another thread didn't insert the same table in between */
if ((old_share= hash_search(&table_def_cache, (uchar*) key, key_length)))
{
(void) pthread_mutex_lock(&share->mutex);
free_table_share(share);
share= old_share;
goto found;
}
#endif
/* /*
Lock mutex to be able to read table definition from file without Lock mutex to be able to read table definition from file without
conflicts conflicts
@@ -388,29 +371,11 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (my_hash_insert(&table_def_cache, (uchar*) share)) if (my_hash_insert(&table_def_cache, (uchar*) share))
{ {
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
(void) pthread_mutex_unlock(&share->mutex);
#endif
free_table_share(share); free_table_share(share);
DBUG_RETURN(0); // return error DBUG_RETURN(0); // return error
} }
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (open_table_def(thd, share, db_flags)) if (open_table_def(thd, share, db_flags))
{ {
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
/*
No such table or wrong table definition file
Lock first the table cache and then the mutex.
This will ensure that no other thread is using the share
structure.
*/
(void) pthread_mutex_unlock(&share->mutex);
(void) pthread_mutex_lock(&LOCK_open);
(void) pthread_mutex_lock(&share->mutex);
#endif
*error= share->error; *error= share->error;
(void) hash_delete(&table_def_cache, (uchar*) share); (void) hash_delete(&table_def_cache, (uchar*) share);
DBUG_RETURN(0); DBUG_RETURN(0);
@@ -429,9 +394,6 @@ found:
/* We must do a lock to ensure that the structure is initialized */ /* We must do a lock to ensure that the structure is initialized */
(void) pthread_mutex_lock(&share->mutex); (void) pthread_mutex_lock(&share->mutex);
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (share->error) if (share->error)
{ {
/* Table definition contained an error */ /* Table definition contained an error */
@@ -618,52 +580,6 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
} }
pthread_mutex_unlock(&share->mutex); pthread_mutex_unlock(&share->mutex);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
if (to_be_deleted)
{
/*
We must try again with new locks as we must get LOCK_open
before share->mutex
*/
pthread_mutex_unlock(&share->mutex);
pthread_mutex_lock(&LOCK_open);
pthread_mutex_lock(&share->mutex);
if (!share->ref_count)
{ // No one is using this now
TABLE_SHARE *name_lock;
if (share->replace_with_name_lock && (name_lock=get_name_lock(share)))
{
/*
This code is execured when someone does FLUSH TABLES while on has
locked tables.
*/
(void) hash_search(&def_cache,(uchar*) key,key_length);
hash_replace(&def_cache, def_cache.current_record,(uchar*) name_lock);
}
else
{
/* Remove table definition */
hash_delete(&def_cache,(uchar*) share);
}
pthread_mutex_unlock(&LOCK_open);
free_table_share(share);
}
else
{
pthread_mutex_unlock(&LOCK_open);
if (type == RELEASE_WAIT_FOR_DROP)
wait_for_table(share, "Waiting for close");
else
pthread_mutex_unlock(&share->mutex);
}
}
else if (type == RELEASE_WAIT_FOR_DROP)
wait_for_table(share, "Waiting for close");
else
pthread_mutex_unlock(&share->mutex);
#endif
} }

View File

@@ -3301,6 +3301,7 @@ end_with_restore_list:
can free its locks if LOCK TABLES locked some tables before finding can free its locks if LOCK TABLES locked some tables before finding
that it can't lock a table in its list that it can't lock a table in its list
*/ */
ha_autocommit_or_rollback(thd, 1);
end_active_trans(thd); end_active_trans(thd);
thd->options&= ~(OPTION_TABLE_LOCK); thd->options&= ~(OPTION_TABLE_LOCK);
} }
@@ -4304,20 +4305,6 @@ create_sp_error:
} }
break; break;
} }
#ifdef NOT_USED
case SQLCOM_SHOW_STATUS_PROC:
{
res= sp_show_status_routine(thd, TYPE_ENUM_PROCEDURE,
(lex->wild ? lex->wild->ptr() : NullS));
break;
}
case SQLCOM_SHOW_STATUS_FUNC:
{
res= sp_show_status_routine(thd, TYPE_ENUM_FUNCTION,
(lex->wild ? lex->wild->ptr() : NullS));
break;
}
#endif
#ifndef DBUG_OFF #ifndef DBUG_OFF
case SQLCOM_SHOW_PROC_CODE: case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE: case SQLCOM_SHOW_FUNC_CODE:

View File

@@ -155,11 +155,11 @@ public:
virtual void cleanup_stmt(); virtual void cleanup_stmt();
bool set_name(LEX_STRING *name); bool set_name(LEX_STRING *name);
inline void close_cursor() { delete cursor; cursor= 0; } inline void close_cursor() { delete cursor; cursor= 0; }
inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
bool prepare(const char *packet, uint packet_length); bool prepare(const char *packet, uint packet_length);
bool execute(String *expanded_query, bool open_cursor); bool execute(String *expanded_query, bool open_cursor);
/* Destroy this statement */ /* Destroy this statement */
bool deallocate(); void deallocate();
private: private:
/** /**
Store the parsed tree of a prepared statement here. Store the parsed tree of a prepared statement here.
@@ -198,7 +198,7 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
*/ */
static Prepared_statement * static Prepared_statement *
find_prepared_statement(THD *thd, ulong id, const char *where) find_prepared_statement(THD *thd, ulong id)
{ {
/* /*
To strictly separate namespaces of SQL prepared statements and C API To strictly separate namespaces of SQL prepared statements and C API
@@ -208,12 +208,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where)
Statement *stmt= thd->stmt_map.find(id); Statement *stmt= thd->stmt_map.find(id);
if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT) if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT)
{ return NULL;
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf),
where);
return 0;
}
return (Prepared_statement *) stmt; return (Prepared_statement *) stmt;
} }
@@ -2121,8 +2117,13 @@ void mysql_sql_stmt_prepare(THD *thd)
If there is a statement with the same name, remove it. It is ok to If there is a statement with the same name, remove it. It is ok to
remove old and fail to insert a new one at the same time. remove old and fail to insert a new one at the same time.
*/ */
if (stmt->deallocate()) if (stmt->is_in_use())
{
my_error(ER_PS_NO_RECURSION, MYF(0));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}
stmt->deallocate();
} }
if (! (query= get_dynamic_sql_string(lex, &query_len)) || if (! (query= get_dynamic_sql_string(lex, &query_len)) ||
@@ -2320,8 +2321,13 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
/* First of all clear possible warnings from the previous command */ /* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
llstr(stmt_id, llbuf), "mysql_stmt_execute");
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.set_query_source(stmt->query, stmt->query_length); thd->profiling.set_query_source(stmt->query, stmt->query_length);
@@ -2458,8 +2464,13 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
/* First of all clear possible warnings from the previous command */ /* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
status_var_increment(thd->status_var.com_stmt_fetch); status_var_increment(thd->status_var.com_stmt_fetch);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
llstr(stmt_id, llbuf), "mysql_stmt_fetch");
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}
cursor= stmt->cursor; cursor= stmt->cursor;
if (!cursor) if (!cursor)
@@ -2520,8 +2531,13 @@ void mysql_stmt_reset(THD *thd, char *packet)
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
status_var_increment(thd->status_var.com_stmt_reset); status_var_increment(thd->status_var.com_stmt_reset);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
llstr(stmt_id, llbuf), "mysql_stmt_reset");
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}
stmt->close_cursor(); stmt->close_cursor();
@@ -2557,15 +2573,15 @@ void mysql_stmt_close(THD *thd, char *packet)
thd->main_da.disable_status(); thd->main_da.disable_status();
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close"))) if (!(stmt= find_prepared_statement(thd, stmt_id)))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/* /*
The only way currently a statement can be deallocated when it's The only way currently a statement can be deallocated when it's
in use is from within Dynamic SQL. in use is from within Dynamic SQL.
*/ */
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE)); DBUG_ASSERT(! stmt->is_in_use());
(void) stmt->deallocate(); stmt->deallocate();
general_log_print(thd, thd->command, NullS); general_log_print(thd, thd->command, NullS);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
@@ -2592,14 +2608,15 @@ void mysql_sql_stmt_close(THD *thd)
name->str)); name->str));
if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
name->length, name->str, "DEALLOCATE PREPARE"); name->length, name->str, "DEALLOCATE PREPARE");
return; else if (stmt->is_in_use())
} my_error(ER_PS_NO_RECURSION, MYF(0));
else
if (stmt->deallocate() == 0) {
stmt->deallocate();
my_ok(thd); my_ok(thd);
}
} }
/** /**
@@ -2633,17 +2650,13 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */ /* Minimal size of long data packet is 6 bytes */
if (packet_length < MYSQL_LONG_DATA_HEADER) if (packet_length < MYSQL_LONG_DATA_HEADER)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data");
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}
#endif #endif
stmt_id= uint4korr(packet); stmt_id= uint4korr(packet);
packet+= 4; packet+= 4;
if (!(stmt=find_prepared_statement(thd, stmt_id, if (!(stmt=find_prepared_statement(thd, stmt_id)))
"mysql_stmt_send_long_data")))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
param_number= uint2korr(packet); param_number= uint2korr(packet);
@@ -3186,16 +3199,10 @@ error:
/** Common part of DEALLOCATE PREPARE and mysql_stmt_close. */ /** Common part of DEALLOCATE PREPARE and mysql_stmt_close. */
bool Prepared_statement::deallocate() void Prepared_statement::deallocate()
{ {
/* We account deallocate in the same manner as mysql_stmt_close */ /* We account deallocate in the same manner as mysql_stmt_close */
status_var_increment(thd->status_var.com_stmt_close); status_var_increment(thd->status_var.com_stmt_close);
if (flags & (uint) IS_IN_USE)
{
my_error(ER_PS_NO_RECURSION, MYF(0));
return TRUE;
}
/* Statement map calls delete stmt on erase */ /* Statement map calls delete stmt on erase */
thd->stmt_map.erase(this); thd->stmt_map.erase(this);
return FALSE;
} }

View File

@@ -853,8 +853,9 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order) Item **conds, uint order_num, ORDER *order)
{ {
Item *fake_conds= 0; Item *fake_conds= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
TABLE *table= table_list->table; TABLE *table= table_list->table;
TABLE_LIST tables; #endif
List<Item> all_fields; List<Item> all_fields;
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update"); DBUG_ENTER("mysql_prepare_update");
@@ -878,9 +879,6 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
table_list->register_want_access(SELECT_ACL); table_list->register_want_access(SELECT_ACL);
#endif #endif
bzero((char*) &tables,sizeof(tables)); // For ORDER BY
tables.table= table;
tables.alias= table_list->alias;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &select_lex->context, if (setup_tables_and_check_access(thd, &select_lex->context,

View File

@@ -634,6 +634,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
my_printf_error(0, "MyISAM table '%s' is in use " my_printf_error(0, "MyISAM table '%s' is in use "
"(most likely by a MERGE table). Try FLUSH TABLES.", "(most likely by a MERGE table). Try FLUSH TABLES.",
MYF(0), name + dirname_length(name)); MYF(0), name + dirname_length(name));
my_errno= HA_ERR_TABLE_EXIST;
goto err; goto err;
} }