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

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


mysql-test/r/create.result:
  Auto merged
mysql-test/r/ps.result:
  Auto merged
mysql-test/r/sp.result:
  Auto merged
mysql-test/t/create.test:
  Auto merged
mysql-test/t/ps.test:
  Auto merged
mysql-test/t/sp.test:
  Auto merged
sql/item_strfunc.cc:
  Auto merged
sql/sp.cc:
  Auto merged
sql/sp.h:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sp_head.h:
  Auto merged
sql/sql_db.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_trigger.cc:
  Auto merged
sql/sql_view.cc:
  Auto merged
sql/table.h:
  Auto merged
sql/tztime.cc:
  Auto merged
include/my_sys.h:
  Manual merge (second attempt).
mysql-test/r/bdb.result:
  Manual merge (second attempt).
mysql-test/t/bdb.test:
  Manual merge (second attempt).
mysys/my_malloc.c:
  Manual merge (second attempt).
mysys/safemalloc.c:
  Manual merge (second attempt).
sql/ha_federated.cc:
  Manual merge (second attempt).
sql/log_event.cc:
  Manual merge (second attempt).
sql/set_var.cc:
  Manual merge (second attempt).
sql/set_var.h:
  Manual merge (second attempt).
sql/slave.cc:
  Manual merge (second attempt).
sql/slave.h:
  Manual merge (second attempt).
sql/sql_class.h:
  Manual merge (second attempt).
sql/sql_table.cc:
  Manual merge (second attempt).
sql/sql_udf.cc:
  Manual merge (second attempt).
sql/sql_yacc.yy:
  Manual merge (second attempt).
This commit is contained in:
unknown 2006-07-06 22:55:48 +04:00
commit df9b4754b7
31 changed files with 649 additions and 306 deletions

View file

@ -163,7 +163,7 @@ extern gptr my_realloc(gptr oldpoint,uint Size,myf MyFlags);
extern void my_no_flags_free(gptr ptr);
extern gptr my_memdup(const byte *from,uint length,myf MyFlags);
extern char *my_strdup(const char *from,myf MyFlags);
extern char *my_strndup(const byte *from, uint length,
extern char *my_strndup(const char *from, uint length,
myf MyFlags);
/* we do use FG (as a no-op) in below so that a typo on FG is caught */
#define my_free(PTR,FG) ((void)FG,my_no_flags_free(PTR))

View file

@ -620,7 +620,7 @@ create database mysqltest;
use mysqltest;
drop database mysqltest;
create table test.t1 like x;
ERROR 42000: Incorrect database name 'NULL'
ERROR 3D000: No database selected
drop table if exists test.t1;
create database mysqltest;
use mysqltest;

View file

@ -1158,3 +1158,108 @@ Warnings:
Error 1146 Table 'test.t4' doesn't exist
deallocate prepare stmt;
drop table t1, t2, t3;
create database mysqltest_long_database_name_to_thrash_heap;
use test;
create table t1 (i int);
prepare stmt from "alter table test.t1 rename t1";
use mysqltest_long_database_name_to_thrash_heap;
execute stmt;
show tables like 't1';
Tables_in_mysqltest_long_database_name_to_thrash_heap (t1)
prepare stmt from "alter table test.t1 rename t1";
use test;
execute stmt;
show tables like 't1';
Tables_in_test (t1)
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
Tables_in_mysqltest_long_database_name_to_thrash_heap (t1)
t1
deallocate prepare stmt;
use mysqltest_long_database_name_to_thrash_heap;
prepare stmt_create from "create table t1 (i int)";
prepare stmt_insert from "insert into t1 (i) values (1)";
prepare stmt_update from "update t1 set i=2";
prepare stmt_delete from "delete from t1 where i=2";
prepare stmt_select from "select * from t1";
prepare stmt_alter from "alter table t1 add column (b int)";
prepare stmt_alter1 from "alter table t1 drop column b";
prepare stmt_analyze from "analyze table t1";
prepare stmt_optimize from "optimize table t1";
prepare stmt_show from "show tables like 't1'";
prepare stmt_truncate from "truncate table t1";
prepare stmt_drop from "drop table t1";
drop table t1;
use test;
execute stmt_create;
show tables like 't1';
Tables_in_test (t1)
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
Tables_in_mysqltest_long_database_name_to_thrash_heap (t1)
t1
use test;
execute stmt_insert;
select * from mysqltest_long_database_name_to_thrash_heap.t1;
i
1
execute stmt_update;
select * from mysqltest_long_database_name_to_thrash_heap.t1;
i
2
execute stmt_delete;
execute stmt_select;
i
execute stmt_alter;
show columns from mysqltest_long_database_name_to_thrash_heap.t1;
Field Type Null Key Default Extra
i int(11) YES NULL
b int(11) YES NULL
execute stmt_alter1;
show columns from mysqltest_long_database_name_to_thrash_heap.t1;
Field Type Null Key Default Extra
i int(11) YES NULL
execute stmt_analyze;
Table Op Msg_type Msg_text
mysqltest_long_database_name_to_thrash_heap.t1 analyze status Table is already up to date
execute stmt_optimize;
Table Op Msg_type Msg_text
mysqltest_long_database_name_to_thrash_heap.t1 optimize status Table is already up to date
execute stmt_show;
Tables_in_mysqltest_long_database_name_to_thrash_heap (t1)
t1
execute stmt_truncate;
execute stmt_drop;
show tables like 't1';
Tables_in_test (t1)
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
Tables_in_mysqltest_long_database_name_to_thrash_heap (t1)
drop database mysqltest_long_database_name_to_thrash_heap;
prepare stmt_create from "create table t1 (i int)";
ERROR 3D000: No database selected
prepare stmt_insert from "insert into t1 (i) values (1)";
ERROR 3D000: No database selected
prepare stmt_update from "update t1 set i=2";
ERROR 3D000: No database selected
prepare stmt_delete from "delete from t1 where i=2";
ERROR 3D000: No database selected
prepare stmt_select from "select * from t1";
ERROR 3D000: No database selected
prepare stmt_alter from "alter table t1 add column (b int)";
ERROR 3D000: No database selected
prepare stmt_alter1 from "alter table t1 drop column b";
ERROR 3D000: No database selected
prepare stmt_analyze from "analyze table t1";
ERROR 3D000: No database selected
prepare stmt_optimize from "optimize table t1";
ERROR 3D000: No database selected
prepare stmt_show from "show tables like 't1'";
ERROR 3D000: No database selected
prepare stmt_truncate from "truncate table t1";
ERROR 3D000: No database selected
prepare stmt_drop from "drop table t1";
ERROR 3D000: No database selected
create temporary table t1 (i int);
ERROR 3D000: No database selected
use test;

View file

@ -5000,6 +5000,52 @@ CALL bug18037_p2()|
DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2|
use test|
create table t3 (i int)|
insert into t3 values (1), (2)|
create database mysqltest1|
use mysqltest1|
create function bug17199() returns varchar(2) deterministic return 'ok'|
use test|
select *, mysqltest1.bug17199() from t3|
i mysqltest1.bug17199()
1 ok
2 ok
use mysqltest1|
create function bug18444(i int) returns int no sql deterministic return i + 1|
use test|
select mysqltest1.bug18444(i) from t3|
mysqltest1.bug18444(i)
2
3
drop database mysqltest1|
create database mysqltest1 charset=utf8|
create database mysqltest2 charset=utf8|
create procedure mysqltest1.p1()
begin
-- alters the default collation of database test
alter database character set koi8r;
end|
use mysqltest1|
call p1()|
show create database mysqltest1|
Database Create Database
mysqltest1 CREATE DATABASE `mysqltest1` /*!40100 DEFAULT CHARACTER SET koi8r */
show create database mysqltest2|
Database Create Database
mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET utf8 */
alter database mysqltest1 character set utf8|
use mysqltest2|
call mysqltest1.p1()|
show create database mysqltest1|
Database Create Database
mysqltest1 CREATE DATABASE `mysqltest1` /*!40100 DEFAULT CHARACTER SET koi8r */
show create database mysqltest2|
Database Create Database
mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET utf8 */
drop database mysqltest1|
drop database mysqltest2|
use test|
drop table if exists t3|
drop procedure if exists bug15217|
create table t3 as select 1|

View file

@ -521,7 +521,7 @@ DROP TABLE t12913;
create database mysqltest;
use mysqltest;
drop database mysqltest;
--error 1102
--error ER_NO_DB_ERROR
create table test.t1 like x;
--disable_warnings
drop table if exists test.t1;

View file

@ -1146,4 +1146,122 @@ execute stmt;
execute stmt;
deallocate prepare stmt;
drop table t1, t2, t3;
#
# Bug#17199 "Table not found" error occurs if the query contains a call
# to a function from another database.
# Test prepared statements- related behaviour.
#
#
# ALTER TABLE RENAME and Prepared Statements: wrong DB name buffer was used
# in ALTER ... RENAME which caused memory corruption in prepared statements.
# No need to fix this problem in 4.1 as ALTER TABLE is not allowed in
# Prepared Statements in 4.1.
#
create database mysqltest_long_database_name_to_thrash_heap;
use test;
create table t1 (i int);
prepare stmt from "alter table test.t1 rename t1";
use mysqltest_long_database_name_to_thrash_heap;
execute stmt;
show tables like 't1';
prepare stmt from "alter table test.t1 rename t1";
use test;
execute stmt;
show tables like 't1';
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
deallocate prepare stmt;
#
# Check that a prepared statement initializes its current database at
# PREPARE, and then works correctly even if the current database has been
# changed.
#
use mysqltest_long_database_name_to_thrash_heap;
# Necessary for preparation of INSERT/UPDATE/DELETE to succeed
prepare stmt_create from "create table t1 (i int)";
prepare stmt_insert from "insert into t1 (i) values (1)";
prepare stmt_update from "update t1 set i=2";
prepare stmt_delete from "delete from t1 where i=2";
prepare stmt_select from "select * from t1";
prepare stmt_alter from "alter table t1 add column (b int)";
prepare stmt_alter1 from "alter table t1 drop column b";
prepare stmt_analyze from "analyze table t1";
prepare stmt_optimize from "optimize table t1";
prepare stmt_show from "show tables like 't1'";
prepare stmt_truncate from "truncate table t1";
prepare stmt_drop from "drop table t1";
# Drop the table that was used to prepare INSERT/UPDATE/DELETE: we will
# create a new one by executing stmt_create
drop table t1;
# Switch the current database
use test;
# Check that all prepared statements operate on the database that was
# active at PREPARE
execute stmt_create;
# should return empty set
show tables like 't1';
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
use test;
execute stmt_insert;
select * from mysqltest_long_database_name_to_thrash_heap.t1;
execute stmt_update;
select * from mysqltest_long_database_name_to_thrash_heap.t1;
execute stmt_delete;
execute stmt_select;
execute stmt_alter;
show columns from mysqltest_long_database_name_to_thrash_heap.t1;
execute stmt_alter1;
show columns from mysqltest_long_database_name_to_thrash_heap.t1;
execute stmt_analyze;
execute stmt_optimize;
execute stmt_show;
execute stmt_truncate;
execute stmt_drop;
show tables like 't1';
use mysqltest_long_database_name_to_thrash_heap;
show tables like 't1';
#
# Attempt a statement PREPARE when there is no current database:
# is expected to return an error.
#
drop database mysqltest_long_database_name_to_thrash_heap;
--error ER_NO_DB_ERROR
prepare stmt_create from "create table t1 (i int)";
--error ER_NO_DB_ERROR
prepare stmt_insert from "insert into t1 (i) values (1)";
--error ER_NO_DB_ERROR
prepare stmt_update from "update t1 set i=2";
--error ER_NO_DB_ERROR
prepare stmt_delete from "delete from t1 where i=2";
--error ER_NO_DB_ERROR
prepare stmt_select from "select * from t1";
--error ER_NO_DB_ERROR
prepare stmt_alter from "alter table t1 add column (b int)";
--error ER_NO_DB_ERROR
prepare stmt_alter1 from "alter table t1 drop column b";
--error ER_NO_DB_ERROR
prepare stmt_analyze from "analyze table t1";
--error ER_NO_DB_ERROR
prepare stmt_optimize from "optimize table t1";
--error ER_NO_DB_ERROR
prepare stmt_show from "show tables like 't1'";
--error ER_NO_DB_ERROR
prepare stmt_truncate from "truncate table t1";
--error ER_NO_DB_ERROR
prepare stmt_drop from "drop table t1";
#
# The above has automatically deallocated all our statements.
#
# Attempt to CREATE a temporary table when no DB used: it should fail
# This proves that no table can be used without explicit specification of
# its database if there is no current database.
#
--error ER_NO_DB_ERROR
create temporary table t1 (i int);
#
# Restore the old environemnt
#
use test;
# End of 5.0 tests

View file

@ -5893,6 +5893,52 @@ DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2|
#
# Bug#17199: "Table not found" error occurs if the query contains a call
# to a function from another database.
# See also ps.test for an additional test case for this bug.
#
use test|
create table t3 (i int)|
insert into t3 values (1), (2)|
create database mysqltest1|
use mysqltest1|
create function bug17199() returns varchar(2) deterministic return 'ok'|
use test|
select *, mysqltest1.bug17199() from t3|
#
# Bug#18444: Fully qualified stored function names don't work correctly
# in select statements
#
use mysqltest1|
create function bug18444(i int) returns int no sql deterministic return i + 1|
use test|
select mysqltest1.bug18444(i) from t3|
drop database mysqltest1|
#
# Check that current database has no influence to a stored procedure
#
create database mysqltest1 charset=utf8|
create database mysqltest2 charset=utf8|
create procedure mysqltest1.p1()
begin
-- alters the default collation of database test
alter database character set koi8r;
end|
use mysqltest1|
call p1()|
show create database mysqltest1|
show create database mysqltest2|
alter database mysqltest1 character set utf8|
use mysqltest2|
call mysqltest1.p1()|
show create database mysqltest1|
show create database mysqltest2|
drop database mysqltest1|
drop database mysqltest2|
#
# Restore the old environemnt
use test|
#
# Bug#15217 "Using a SP cursor on a table created with PREPARE fails with
# weird error". Check that the code that is supposed to work at

View file

@ -83,7 +83,7 @@ char *my_strdup(const char *from, myf my_flags)
}
char *my_strndup(const byte *from, uint length, myf my_flags)
char *my_strndup(const char *from, uint length, myf my_flags)
{
gptr ptr;
if ((ptr=my_malloc(length+1,my_flags)) != 0)

View file

@ -525,9 +525,8 @@ char *_my_strdup(const char *from, const char *filename, uint lineno,
} /* _my_strdup */
char *_my_strndup(const byte *from, uint length,
const char *filename, uint lineno,
myf MyFlags)
char *_my_strndup(const char *from, uint length, const char *filename,
uint lineno, myf MyFlags)
{
gptr ptr;
if ((ptr=_mymalloc(length+1,filename,lineno,MyFlags)) != 0)

View file

@ -629,10 +629,8 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
DBUG_PRINT("info", ("Length: %d", table->s->connect_string.length));
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
table->s->connect_string.str));
share->scheme= my_strndup((const byte*)table->s->
connect_string.str,
table->s->connect_string.length,
MYF(0));
share->scheme= my_strndup(table->s->connect_string.str,
table->s->connect_string.length, MYF(0));
// Add a null for later termination of table name
share->scheme[table->s->connect_string.length]= 0;

View file

@ -1667,13 +1667,13 @@ String *Item_func_database::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
THD *thd= current_thd;
if (!thd->db)
if (thd->db == NULL)
{
null_value= 1;
return 0;
}
else
str->copy((const char*) thd->db,(uint) strlen(thd->db),system_charset_info);
str->copy(thd->db, thd->db_length, system_charset_info);
return str;
}

View file

@ -1928,9 +1928,10 @@ end:
don't suffer from these assignments to 0 as DROP TEMPORARY
TABLE uses the db.table syntax.
*/
thd->db= thd->catalog= 0; // prevent db from being freed
thd->catalog= 0;
thd->reset_db(NULL, 0); // prevent db from being freed
thd->query= 0; // just to be sure
thd->query_length= thd->db_length =0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd);
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
@ -2954,7 +2955,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
TABLE_LIST tables;
bzero((char*) &tables,sizeof(tables));
tables.db = thd->db;
tables.db= thd->strmake(thd->db, thd->db_length);
tables.alias = tables.table_name = (char*) table_name;
tables.lock_type = TL_WRITE;
tables.updating= 1;
@ -3049,7 +3050,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
ex.skip_lines = skip_lines;
List<Item> field_list;
thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
set_fields(thd->db, field_list, &thd->main_lex.select_lex.context);
set_fields(tables.db, field_list, &thd->main_lex.select_lex.context);
thd->variables.pseudo_thread_id= thread_id;
List<Item> set_fields;
if (net)
@ -3096,11 +3097,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
error:
thd->net.vio = 0;
char *save_db= thd->db;
const char *remember_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db= thd->catalog= 0;
thd->catalog= 0;
thd->reset_db(NULL, 0);
thd->query= 0;
thd->query_length= thd->db_length= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd);
if (thd->query_error)
@ -3117,7 +3119,7 @@ error:
}
slave_print_msg(ERROR_LEVEL, rli, sql_errno,"\
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
err, (char*)table_name, print_slave_db_safe(save_db));
err, (char*)table_name, print_slave_db_safe(remember_db));
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
return 1;
}
@ -3127,7 +3129,7 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
{
slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR, "\
Fatal error running LOAD DATA INFILE on table '%s'. Default database: '%s'",
(char*)table_name, print_slave_db_safe(save_db));
(char*)table_name, print_slave_db_safe(remember_db));
return 1;
}
@ -3202,8 +3204,7 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
llstr(pos_arg, buff), flags));
#endif
if (flags & DUP_NAME)
new_log_ident= my_strndup((const byte*) new_log_ident_arg,
ident_len, MYF(MY_WME));
new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
DBUG_VOID_RETURN;
}
#endif
@ -3226,9 +3227,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
(header_size+post_header_len));
ident_offset = post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
new_log_ident= my_strndup((byte*) buf + ident_offset,
(uint) ident_len,
MYF(MY_WME));
new_log_ident= my_strndup(buf + ident_offset, (uint) ident_len, MYF(MY_WME));
DBUG_VOID_RETURN;
}

View file

@ -1097,7 +1097,7 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
uint new_length= (var ? var->value->str_value.length() : 0);
if (!old_value)
old_value= (char*) "";
if (!(res= my_strndup((byte*)old_value, new_length, MYF(0))))
if (!(res= my_strndup(old_value, new_length, MYF(0))))
return 1;
/*
Replace the old value in such a way that the any thread using
@ -2632,7 +2632,7 @@ bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
old_value= make_default_log_name(buff, log_ext);
str_length= strlen(old_value);
}
if (!(res= my_strndup((byte*)old_value, str_length, MYF(MY_FAE+MY_WME))))
if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
{
result= 1;
goto err;

View file

@ -1055,7 +1055,7 @@ public:
uint name_length_arg, gptr data_arg)
:name_length(name_length_arg), data(data_arg)
{
name= my_strndup((byte*) name_arg, name_length, MYF(MY_WME));
name= my_strndup(name_arg, name_length, MYF(MY_WME));
links->push_back(this);
}
inline bool cmp(const char *name_cmp, uint length)

View file

@ -1347,9 +1347,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
// save old db in case we are creating in a different database
save_db = thd->db;
save_db_length= thd->db_length;
thd->db = (char*)db;
DBUG_ASSERT(thd->db != 0);
thd->db_length= strlen(thd->db);
DBUG_ASSERT(db != 0);
thd->reset_db((char*)db, strlen(db));
mysql_parse(thd, thd->query, packet_len); // run create table
thd->db = save_db; // leave things the way the were before
thd->db_length= save_db_length;
@ -3511,8 +3510,9 @@ err:
sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s",
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
thd->query_length= thd->db_length= 0;
thd->query= 0; // extra safety
thd->query_length= 0;
thd->reset_db(NULL, 0);
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql)
{
@ -3760,8 +3760,10 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
should already have done these assignments (each event which sets these
variables is supposed to set them to 0 before terminating)).
*/
thd->query= thd->db= thd->catalog= 0;
thd->query_length= thd->db_length= 0;
thd->catalog= 0;
thd->reset_db(NULL, 0);
thd->query= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock);

107
sql/sp.cc
View file

@ -406,7 +406,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
{
LEX *old_lex= thd->lex, newlex;
String defstr;
char olddb[128];
char old_db_buf[NAME_LEN+1];
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
ulong old_sql_mode= thd->variables.sql_mode;
ha_rows old_select_limit= thd->variables.select_limit;
@ -450,9 +451,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
goto end;
}
dbchanged= FALSE;
if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
1, &dbchanged)))
if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
goto end;
lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
@ -462,14 +461,14 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
{
sp_head *sp= newlex.sphead;
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
goto end;
delete sp;
ret= SP_PARSE_ERROR;
}
else
{
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
goto end;
*sphp= newlex.sphead;
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
@ -507,15 +506,14 @@ db_create_routine(THD *thd, int type, sp_head *sp)
int ret;
TABLE *table;
char definer[USER_HOST_BUFF_SIZE];
char olddb[128];
char old_db_buf[NAME_LEN+1];
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
sp->m_name.str));
dbchanged= FALSE;
if ((ret= sp_use_new_db(thd, sp->m_db.str, olddb, sizeof(olddb),
0, &dbchanged)))
if ((ret= sp_use_new_db(thd, sp->m_db, &old_db, 0, &dbchanged)))
{
ret= SP_NO_DB_ERROR;
goto done;
@ -642,7 +640,7 @@ db_create_routine(THD *thd, int type, sp_head *sp)
done:
close_thread_tables(thd);
if (dbchanged)
(void)mysql_change_db(thd, olddb, 1);
(void) mysql_change_db(thd, old_db.str, 1);
DBUG_RETURN(ret);
}
@ -1815,49 +1813,76 @@ create_string(THD *thd, String *buf,
}
//
// Utilities...
//
/*
Change the current database if needed.
SYNOPSIS
sp_use_new_db()
thd thread handle
new_db new database name (a string and its length)
old_db [IN] str points to a buffer where to store the old
database, length contains the size of the buffer
[OUT] if old db was not NULL, its name is copied
to the buffer pointed at by str and length is updated
accordingly. Otherwise str[0] is set to '\0' and length
is set to 0. The out parameter should be used only if
the database name has been changed (see dbchangedp).
dbchangedp [OUT] is set to TRUE if the current database is changed,
FALSE otherwise. A database is not changed if the old
name is the same as the new one, both names are empty,
or an error has occurred.
RETURN VALUE
0 success
1 access denied or out of memory (the error message is
set in THD)
*/
int
sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db,
bool no_access_check, bool *dbchangedp)
{
bool changeit;
int ret;
static char empty_c_string[1]= {0}; /* used for not defined db */
DBUG_ENTER("sp_use_new_db");
DBUG_PRINT("enter", ("newdb: %s", newdb));
DBUG_PRINT("enter", ("newdb: %s", new_db.str));
if (! newdb)
newdb= (char *)"";
if (thd->db && thd->db[0])
/*
Set new_db to an empty string if it's NULL, because mysql_change_db
requires a non-NULL argument.
new_db.str can be NULL only if we're restoring the old database after
execution of a stored procedure and there were no current database
selected. The stored procedure itself must always have its database
initialized.
*/
if (new_db.str == NULL)
new_db.str= empty_c_string;
if (thd->db)
{
if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
changeit= 0;
else
{
changeit= 1;
strnmov(olddb, thd->db, olddblen);
}
old_db->length= (strmake(old_db->str, thd->db, old_db->length) -
old_db->str);
}
else
{ // thd->db empty
if (newdb[0])
changeit= 1;
else
changeit= 0;
olddb[0] = '\0';
{
old_db->str[0]= '\0';
old_db->length= 0;
}
if (!changeit)
/* Don't change the database if the new name is the same as the old one. */
if (my_strcasecmp(system_charset_info, old_db->str, new_db.str) == 0)
{
*dbchangedp= FALSE;
DBUG_RETURN(0);
}
else
{
int ret= mysql_change_db(thd, newdb, no_access_check);
if (! ret)
*dbchangedp= TRUE;
DBUG_RETURN(ret);
}
ret= mysql_change_db(thd, new_db.str, no_access_check);
*dbchangedp= ret == 0;
DBUG_RETURN(ret);
}

View file

@ -104,15 +104,15 @@ extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first);
TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup);
void close_proc_table(THD *thd, Open_tables_state *backup);
//
// Utilities...
//
// Do a "use newdb". The current db is stored at olddb.
// If newdb is the same as the current one, nothing is changed.
// dbchangedp is set to true if the db was actually changed.
/*
Do a "use new_db". The current db is stored at old_db. If new_db is the
same as the current one, nothing is changed. dbchangedp is set to true if
the db was actually changed.
*/
int
sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddbmax,
sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db,
bool no_access_check, bool *dbchangedp);
#endif /* _SP_H_ */

View file

@ -385,24 +385,6 @@ sp_name::init_qname(THD *thd)
m_name.length, m_name.str);
}
sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name)
{
sp_name *qname;
if (! thd->db)
qname= new sp_name(name);
else
{
LEX_STRING db;
db.length= strlen(thd->db);
db.str= thd->strmake(thd->db, db.length);
qname= new sp_name(db, name);
}
qname->init_qname(thd);
return qname;
}
/*
Check that the name 'ident' is ok. It's assumed to be an 'ident'
@ -513,27 +495,20 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
/* During parsing, we must use thd->mem_root */
MEM_ROOT *root= thd->mem_root;
/* We have to copy strings to get them into the right memroot */
if (name)
{
m_db.length= name->m_db.length;
if (name->m_db.length == 0)
m_db.str= NULL;
else
m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
m_name.length= name->m_name.length;
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
DBUG_ASSERT(name);
/* Must be initialized in the parser */
DBUG_ASSERT(name->m_db.str && name->m_db.length);
if (name->m_qname.length == 0)
name->init_qname(thd);
m_qname.length= name->m_qname.length;
m_qname.str= strmake_root(root, name->m_qname.str, m_qname.length);
}
else if (thd->db)
{
m_db.length= thd->db_length;
m_db.str= strmake_root(root, thd->db, m_db.length);
}
/* We have to copy strings to get them into the right memroot */
m_db.length= name->m_db.length;
m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
m_name.length= name->m_name.length;
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
if (name->m_qname.length == 0)
name->init_qname(thd);
m_qname.length= name->m_qname.length;
m_qname.str= strmake_root(root, name->m_qname.str, m_qname.length);
if (m_param_begin && m_param_end)
{
@ -949,7 +924,8 @@ bool
sp_head::execute(THD *thd)
{
DBUG_ENTER("sp_head::execute");
char olddb[128];
char old_db_buf[NAME_LEN+1];
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
sp_rcontext *ctx;
bool err_status= FALSE;
@ -996,10 +972,8 @@ sp_head::execute(THD *thd)
m_first_instance->m_last_cached_sp == this) ||
(m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
dbchanged= FALSE;
if (m_db.length &&
(err_status= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0,
&dbchanged)))
(err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
goto done;
if ((ctx= thd->spcont))
@ -1170,10 +1144,10 @@ sp_head::execute(THD *thd)
{
/*
No access check when changing back to where we came from.
(It would generate an error from mysql_change_db() when olddb=="")
(It would generate an error from mysql_change_db() when old_db=="")
*/
if (! thd->killed)
err_status|= mysql_change_db(thd, olddb, 1);
err_status|= mysql_change_db(thd, old_db.str, 1);
}
m_flags&= ~IS_INVOKED;
DBUG_PRINT("info",
@ -1857,9 +1831,6 @@ sp_head::reset_thd_mem_root(THD *thd)
(ulong) &mem_root, (ulong) &thd->mem_root));
free_list= thd->free_list; // Keep the old list
thd->free_list= NULL; // Start a new one
/* Copy the db, since substatements will point to it */
m_thd_db= thd->db;
thd->db= thd->strmake(thd->db, thd->db_length);
m_thd= thd;
DBUG_VOID_RETURN;
}
@ -1875,7 +1846,6 @@ sp_head::restore_thd_mem_root(THD *thd)
DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
(ulong) &mem_root, (ulong) &thd->mem_root));
thd->free_list= flist; // Restore the old one
thd->db= m_thd_db; // Restore the original db pointer
thd->mem_root= m_thd_root;
m_thd= NULL;
DBUG_VOID_RETURN;

View file

@ -61,13 +61,6 @@ public:
*/
LEX_STRING m_sroutines_key;
sp_name(LEX_STRING name)
: m_name(name)
{
m_db.str= m_qname.str= m_sroutines_key.str= 0;
m_db.length= m_qname.length= m_sroutines_key.length= 0;
}
sp_name(LEX_STRING db, LEX_STRING name)
: m_db(db), m_name(name)
{
@ -101,8 +94,6 @@ public:
{}
};
sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name);
bool
check_routine_name(LEX_STRING name);
@ -356,7 +347,6 @@ private:
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
THD *m_thd; // Set if we have reset mem_root
char *m_thd_db; // Original thd->db pointer
sp_pcontext *m_pcont; // Parse context
List<LEX> m_lex; // Temp. store for the other lex

View file

@ -1135,7 +1135,7 @@ public:
uint tmp_table, global_read_lock;
uint server_status,open_options;
enum enum_thread_type system_thread;
uint32 db_length;
uint db_length;
uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
@ -1443,6 +1443,47 @@ public:
current_stmt_binlog_row_based= FALSE;
#endif
}
/*
Initialize the current database from a NULL-terminated string with length
*/
void 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 && 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));
}
db_length= db ? new_db_len: 0;
}
}
void reset_db(char *new_db, uint new_db_len)
{
db= new_db;
db_length= new_db_len;
}
/*
Copy the current database to the argument. Use the current arena to
allocate memory for a deep copy: current database may be freed after
a statement is parsed but before it's executed.
*/
bool copy_db_to(char **p_db, uint *p_db_length)
{
if (db == NULL)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
return TRUE;
}
*p_db= strmake(db, db_length);
if (p_db_length)
*p_db_length= db_length;
return FALSE;
}
};
@ -1790,7 +1831,7 @@ typedef struct st_sort_buffer {
class Table_ident :public Sql_alloc
{
public:
public:
LEX_STRING db;
LEX_STRING table;
SELECT_LEX_UNIT *sel;

View file

@ -930,8 +930,7 @@ exit:
{
if (!(thd->slave_thread)) /* a slave thread will free it itself */
x_free(thd->db);
thd->db= 0;
thd->db_length= 0;
thd->reset_db(NULL, 0);
}
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
@ -1345,14 +1344,10 @@ end:
{
if (!(thd->slave_thread))
my_free(dbname, MYF(0));
thd->db= NULL;
thd->db_length= 0;
thd->reset_db(NULL, 0);
}
else
{
thd->db= dbname; // THD::~THD will free this
thd->db_length= db_length;
}
thd->reset_db(dbname, db_length); // THD::~THD will free this
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!no_access_check)
sctx->db_access= db_access;

View file

@ -312,9 +312,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
{
if (thd->locked_tables)
{
if (find_locked_table(thd,
table_list->db ? table_list->db : thd->db,
table_list->table_name))
DBUG_ASSERT(table_list->db); /* Must be set in the parser */
if (find_locked_table(thd, table_list->db, table_list->table_name))
{
my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
table_list->table_name);
@ -1401,8 +1400,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
TABLE *table;
DBUG_ENTER("delayed_get_table");
if (!table_list->db)
table_list->db=thd->db;
/* Must be set in the parser */
DBUG_ASSERT(table_list->db);
/* Find the thread which handles this table. */
if (!(tmp=find_handler(thd,table_list)))
@ -1429,15 +1428,15 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_mutex_lock(&LOCK_thread_count);
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
if (!(tmp->thd.db=my_strdup(table_list->db,MYF(MY_WME))) ||
!(tmp->thd.query=my_strdup(table_list->table_name,MYF(MY_WME))))
tmp->thd.set_db(table_list->db, strlen(table_list->db));
tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME));
if (tmp->thd.db == NULL || tmp->thd.query == NULL)
{
delete tmp;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
goto err1;
}
tmp->table_list= *table_list; // Needed to open table
tmp->table_list.db= tmp->thd.db;
tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query;
tmp->lock();
pthread_mutex_lock(&tmp->mutex);

View file

@ -808,6 +808,11 @@ public:
*this= *state;
}
/*
Direct addition to the list of query tables.
If you are using this function, you must ensure that the table
object, in particular table->db member, is initialized.
*/
void add_to_query_tables(TABLE_LIST *table)
{
*(table->prev_global= query_tables_last)= table;

View file

@ -111,8 +111,6 @@ const char *xa_state_names[]={
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
};
static char empty_c_string[1]= {0}; // Used for not defined 'db'
#ifdef __WIN__
static void test_signal(int sig_ptr)
{
@ -315,8 +313,7 @@ int check_user(THD *thd, enum enum_server_command command,
thd->db is saved in caller and needs to be freed by caller if this
function returns 0
*/
thd->db= 0;
thd->db_length= 0;
thd->reset_db(NULL, 0);
if (mysql_change_db(thd, db, FALSE))
{
/* Send the error to the client */
@ -356,9 +353,8 @@ int check_user(THD *thd, enum enum_server_command command,
if connect failed. Also in case of 'CHANGE USER' failure, current
database will be switched to 'no database selected'.
*/
thd->db= 0;
thd->db_length= 0;
thd->reset_db(NULL, 0);
USER_RESOURCES ur;
int res= acl_getroot(thd, &ur, passwd, passwd_len);
#ifndef EMBEDDED_LIBRARY
@ -1365,19 +1361,6 @@ end:
DBUG_RETURN(0);
}
/* This works because items are allocated with sql_alloc() */
void free_items(Item *item)
{
Item *next;
DBUG_ENTER("free_items");
for (; item ; item=next)
{
next=item->next;
item->delete_self();
}
DBUG_VOID_RETURN;
}
/* This works because items are allocated with sql_alloc() */
@ -1389,7 +1372,26 @@ void cleanup_items(Item *item)
DBUG_VOID_RETURN;
}
int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
/*
Handle COM_TABLE_DUMP command
SYNOPSIS
mysql_table_dump
thd thread handle
db database name or an empty string. If empty,
the current database of the connection is used
tbl_name name of the table to dump
NOTES
This function is written to handle one specific command only.
RETURN VALUE
0 success
1 error, the error message is set in THD
*/
static
int mysql_table_dump(THD* thd, char* db, char* tbl_name)
{
TABLE* table;
TABLE_LIST* table_list;
@ -1426,7 +1428,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err;
}
net_flush(&thd->net);
if ((error= table->file->dump(thd,fd)))
if ((error= table->file->dump(thd,-1)))
my_error(ER_GET_ERRNO, MYF(0), error);
err:
@ -1678,7 +1680,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
mysql_table_dump(thd, db, tbl_name, -1);
mysql_table_dump(thd, db, tbl_name);
break;
}
case COM_CHANGE_USER:
@ -1853,11 +1855,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
if (thd->copy_db_to(&table_list.db, 0))
break;
}
pend= strend(packet);
thd->convert_string(&conv_name, system_charset_info,
packet, (uint) (pend-packet), thd->charset());
@ -2205,6 +2204,34 @@ void log_slow_statement(THD *thd)
}
/*
Create a TABLE_LIST object for an INFORMATION_SCHEMA table.
SYNOPSIS
prepare_schema_table()
thd thread handle
lex current lex
table_ident table alias if it's used
schema_table_idx the type of the INFORMATION_SCHEMA table to be
created
DESCRIPTION
This function is used in the parser to convert a SHOW or DESCRIBE
table_name command to a SELECT from INFORMATION_SCHEMA.
It prepares a SELECT_LEX and a TABLE_LIST object to represent the
given command as a SELECT parse tree.
NOTES
Due to the way this function works with memory and LEX it cannot
be used outside the parser (parse tree transformations outside
the parser break PS and SP).
RETURN VALUE
0 success
1 out of memory or SHOW commands are not allowed
in this version of the server.
*/
int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
enum enum_schema_tables schema_table_idx)
{
@ -2233,13 +2260,13 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
DBUG_RETURN(1);
#else
{
char *db= lex->select_lex.db ? lex->select_lex.db : thd->db;
if (!db)
char *db;
if (lex->select_lex.db == NULL &&
thd->copy_db_to(&lex->select_lex.db, 0))
{
my_message(ER_NO_DB_ERROR,
ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(1);
}
db= lex->select_lex.db;
remove_escape(db); // Fix escaped '_'
if (check_db_name(db))
{
@ -2256,11 +2283,6 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
db);
DBUG_RETURN(1);
}
/*
We need to do a copy to make this prepared statement safe if this
was thd->db
*/
lex->select_lex.db= thd->strdup(db);
break;
}
#endif
@ -2797,8 +2819,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_LOAD_MASTER_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!first_table->db)
first_table->db= thd->db;
DBUG_ASSERT(first_table->db); /* Must be set in the parser */
if (check_access(thd, CREATE_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
@ -3053,25 +3075,8 @@ end_with_restore_list:
my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
goto error;
}
if (!select_lex->db)
{
/*
In the case of ALTER TABLE ... RENAME we should supply the
default database if the new name is not explicitly qualified
by a database. (Bug #11493)
*/
if (lex->alter_info.flags & ALTER_RENAME)
{
if (! thd->db)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
goto error;
}
select_lex->db= thd->db;
}
else
select_lex->db= first_table->db;
}
/* Must be set in the parser */
DBUG_ASSERT(select_lex->db);
if (check_access(thd, priv_needed, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)) ||
@ -3824,12 +3829,8 @@ end_with_restore_list:
}
case SQLCOM_ALTER_DB:
{
char *db= lex->name ? lex->name : thd->db;
if (!db)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
break;
}
char *db= lex->name;
DBUG_ASSERT(db); /* Must be set in the parser */
if (!strip_sp(db) || check_db_name(db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db);
@ -4364,23 +4365,11 @@ end_with_restore_list:
case SQLCOM_CREATE_SPFUNCTION:
{
uint namelen;
char *name, *db;
char *name;
int result;
DBUG_ASSERT(lex->sphead != 0);
if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0])
{
if (!thd->db)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
delete lex->sphead;
lex->sphead= 0;
goto error;
}
lex->sphead->m_db.length= strlen(thd->db);
lex->sphead->m_db.str= thd->db;
}
DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
is_schema_db(lex->sphead->m_db.str)))
@ -4497,34 +4486,17 @@ end_with_restore_list:
}
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
/*
We need to copy name and db in order to use them for
check_routine_access which is called after lex->sphead has
been deleted.
*/
name= thd->strdup(name);
lex->sphead->m_db.str= db= thd->strmake(lex->sphead->m_db.str,
lex->sphead->m_db.length);
res= (result= lex->sphead->create(thd));
if (result == SP_OK)
{
/*
We must cleanup the unit and the lex here because
sp_grant_privileges calls (indirectly) db_find_routine,
which in turn may call MYSQLparse with THD::lex.
TODO: fix db_find_routine to use a temporary lex.
*/
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */
if (sp_automatic_privileges && !opt_noacl &&
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
db, name,
lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{
if (sp_grant_privileges(thd, db, name,
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_PROC_AUTO_GRANT_FAIL,
@ -4532,6 +4504,9 @@ end_with_restore_list:
close_thread_tables(thd);
}
#endif
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
send_ok(thd);
}
else
@ -4948,7 +4923,8 @@ end_with_restore_list:
view_store_options(thd, first_table, &buff);
buff.append(STRING_WITH_LEN("VIEW "));
/* Test if user supplied a db (ie: we did not use thd->db) */
if (first_table->db != thd->db && first_table->db[0])
if (first_table->db && first_table->db[0] &&
(thd->db == NULL || strcmp(first_table->db, thd->db)))
{
append_identifier(thd, &buff, first_table->db,
first_table->db_length);
@ -5612,7 +5588,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
(want_access & ~EXTRA_ACL) &&
thd->db)
tables->grant.privilege= want_access;
else if (tables->db && tables->db == thd->db)
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
{
if (found && !grant_option) // db already checked
tables->grant.privilege=found_access;
@ -5760,22 +5736,25 @@ bool check_merge_table_access(THD *thd, char *db,
static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
char *current_db= NULL;
for (; tables; tables= tables->next_global)
{
if (!tables->db)
if (tables->db == NULL)
{
if (!(tables->db=thd->db))
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
MYF(0)); /* purecov: tested */
return TRUE; /* purecov: tested */
}
/*
This code never works and should be removed in 5.1. All tables
that are added to the list of tables should already have its
database field initialized properly (see st_lex::add_table_to_list).
*/
DBUG_ASSERT(0);
if (thd->copy_db_to(&current_db, 0))
return TRUE;
tables->db= current_db;
}
}
return FALSE;
}
/****************************************************************************
Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/
@ -6417,19 +6396,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
else if (thd->db)
{
ptr->db= thd->db;
ptr->db_length= thd->db_length;
}
else
{
/* The following can't be "" as we may do 'casedn_str()' on it */
ptr->db= empty_c_string;
ptr->db_length= 0;
}
if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
ptr->db= thd->strdup(ptr->db);
else if (thd->copy_db_to(&ptr->db, &ptr->db_length))
DBUG_RETURN(0);
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
@ -7646,6 +7614,8 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables)
my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
DBUG_RETURN(TRUE);
}
if (check_db_used(thd, tables))
DBUG_RETURN(TRUE);
DBUG_RETURN(FALSE);
}

View file

@ -4406,7 +4406,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
DBUG_RETURN(TRUE);
}
src_db= table_ident->db.str ? table_ident->db.str : thd->db;
DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
src_db= table_ident->db.str;
/*
Validate the source table

View file

@ -928,8 +928,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
save_db.str= thd->db;
save_db.length= thd->db_length;
thd->db_length= strlen(db);
thd->db= (char *) db;
thd->reset_db((char*) db, strlen(db));
while ((trg_create_str= it++))
{
trg_sql_mode= itm++;
@ -1031,8 +1030,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
lex_end(&lex);
}
thd->db= save_db.str;
thd->db_length= save_db.length;
thd->reset_db(save_db.str, save_db.length);
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
@ -1045,8 +1043,7 @@ err_with_lex_cleanup:
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->db= save_db.str;
thd->db_length= save_db.length;
thd->reset_db(save_db.str, save_db.length);
DBUG_RETURN(1);
}

View file

@ -114,7 +114,8 @@ void udf_init()
READ_RECORD read_record_info;
TABLE *table;
int error;
DBUG_ENTER("udf_init");
DBUG_ENTER("ufd_init");
char db[]= "mysql"; /* A subject to casednstr, can't be constant */
if (initialized)
DBUG_VOID_RETURN;
@ -135,13 +136,12 @@ void udf_init()
initialized = 1;
new_thd->thread_stack= (char*) &new_thd;
new_thd->store_globals();
new_thd->db= my_strdup("mysql", MYF(0));
new_thd->db_length=5;
new_thd->set_db(db, sizeof(db)-1);
bzero((gptr) &tables,sizeof(tables));
tables.alias= tables.table_name= (char*) "func";
tables.lock_type = TL_READ;
tables.db=new_thd->db;
tables.db= db;
if (simple_open_n_lock_tables(new_thd, &tables))
{

View file

@ -452,15 +452,15 @@ bool mysql_create_view(THD *thd,
*/
for (sl= select_lex; sl; sl= sl->next_select())
{
char *db= view->db ? view->db : thd->db;
DBUG_ASSERT(view->db); /* Must be set in the parser */
List_iterator_fast<Item> it(sl->item_list);
Item *item;
fill_effective_table_privileges(thd, &view->grant, db,
fill_effective_table_privileges(thd, &view->grant, view->db,
view->table_name);
while ((item= it++))
{
Item_field *fld;
uint priv= (get_column_grant(thd, &view->grant, db,
uint priv= (get_column_grant(thd, &view->grant, view->db,
view->table_name, item->name) &
VIEW_ANY_ACL);
if ((fld= item->filed_for_view_update()))
@ -643,8 +643,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
if (!parser->ok() || !is_equal(&view_type, parser->type()))
{
my_error(ER_WRONG_OBJECT, MYF(0),
(view->db ? view->db : thd->db), view->table_name, "VIEW");
my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
DBUG_RETURN(-1);
}

View file

@ -1594,12 +1594,18 @@ sp_name:
}
| ident
{
THD *thd= YYTHD;
LEX_STRING db;
if (check_routine_name($1))
{
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
YYABORT;
}
$$= sp_name_current_db_new(YYTHD, $1);
if (thd->copy_db_to(&db.str, &db.length))
YYABORT;
$$= new sp_name(db, $1);
if ($$)
$$->init_qname(YYTHD);
}
;
@ -3184,14 +3190,26 @@ create2:
| LIKE table_ident
{
LEX *lex=Lex;
THD *thd= lex->thd;
if (!(lex->like_name= $2))
YYABORT;
if ($2->db.str == NULL &&
thd->copy_db_to(&($2->db.str), &($2->db.length)))
{
YYABORT;
}
}
| '(' LIKE table_ident ')'
{
LEX *lex=Lex;
THD *thd= lex->thd;
if (!(lex->like_name= $3))
YYABORT;
if ($3->db.str == NULL &&
thd->copy_db_to(&($3->db.str), &($3->db.length)))
{
YYABORT;
}
}
;
@ -4640,8 +4658,10 @@ alter:
lex->key_list.empty();
lex->col_list.empty();
lex->select_lex.init_order();
lex->select_lex.db=lex->name= 0;
lex->name= 0;
lex->like_name= 0;
lex->select_lex.db=
((TABLE_LIST*) lex->select_lex.table_list.first)->db;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= 0;
lex->create_info.default_table_charset= NULL;
@ -4660,8 +4680,11 @@ alter:
opt_create_database_options
{
LEX *lex=Lex;
THD *thd= Lex->thd;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name= $3;
if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL))
YYABORT;
}
| ALTER PROCEDURE sp_name
{
@ -5096,14 +5119,20 @@ alter_list_item:
| RENAME opt_to table_ident
{
LEX *lex=Lex;
THD *thd= lex->thd;
lex->select_lex.db=$3->db.str;
lex->name= $3->table.str;
if (lex->select_lex.db == NULL &&
thd->copy_db_to(&lex->select_lex.db, NULL))
{
YYABORT;
}
if (check_table_name($3->table.str,$3->table.length) ||
$3->db.str && check_db_name($3->db.str))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
YYABORT;
}
lex->name= $3->table.str;
lex->alter_info.flags|= ALTER_RENAME;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
@ -6449,7 +6478,13 @@ simple_expr:
#endif /* HAVE_DLOPEN */
{
LEX *lex= Lex;
sp_name *name= sp_name_current_db_new(YYTHD, $1);
THD *thd= lex->thd;
LEX_STRING db;
if (thd->copy_db_to(&db.str, &db.length))
YYABORT;
sp_name *name= new sp_name(db, $1);
if (name)
name->init_qname(thd);
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
if ($4)
@ -10328,7 +10363,9 @@ grant_ident:
'*'
{
LEX *lex= Lex;
lex->current_select->db= lex->thd->db;
THD *thd= lex->thd;
if (thd->copy_db_to(&lex->current_select->db, NULL))
YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)

View file

@ -695,7 +695,8 @@ typedef struct st_table_list
thr_lock_type lock_type;
uint outer_join; /* Which join type */
uint shared; /* Used in multi-upd */
uint32 db_length, table_name_length;
uint db_length;
uint32 table_name_length;
bool updatable; /* VIEW/TABLE can be updated now */
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */

View file

@ -1560,6 +1560,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
TABLE *table;
Tz_names_entry *tmp_tzname;
my_bool return_val= 1;
char db[]= "mysql";
int res;
DBUG_ENTER("my_tz_init");
@ -1616,13 +1617,12 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
leap seconds shared by all time zones.
*/
thd->db= my_strdup("mysql",MYF(0));
thd->db_length= 5; // Safety
thd->set_db(db, sizeof(db)-1);
bzero((char*) &tables_buff, sizeof(TABLE_LIST));
tables_buff[0].alias= tables_buff[0].table_name=
(char*)"time_zone_leap_second";
tables_buff[0].lock_type= TL_READ;
tables_buff[0].db= thd->db;
tables_buff[0].db= db;
/*
Fill TABLE_LIST for the rest of the time zone describing tables
and link it to first one.