Commit 4d25d215 authored by konstantin@mysql.com's avatar konstantin@mysql.com

Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime

into  mysql.com:/opt/local/work/mysql-5.0-17199
parents 8f4582db 117b76a5
...@@ -607,7 +607,7 @@ create database mysqltest; ...@@ -607,7 +607,7 @@ create database mysqltest;
use mysqltest; use mysqltest;
drop database mysqltest; drop database mysqltest;
create table test.t1 like x; create table test.t1 like x;
ERROR 42000: Incorrect database name 'NULL' ERROR 3D000: No database selected
drop table if exists test.t1; drop table if exists test.t1;
create database mysqltest; create database mysqltest;
use mysqltest; use mysqltest;
......
...@@ -1158,3 +1158,108 @@ Warnings: ...@@ -1158,3 +1158,108 @@ Warnings:
Error 1146 Table 'test.t4' doesn't exist Error 1146 Table 'test.t4' doesn't exist
deallocate prepare stmt; deallocate prepare stmt;
drop table t1, t2, t3; 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;
...@@ -4990,6 +4990,52 @@ CALL bug18037_p2()| ...@@ -4990,6 +4990,52 @@ CALL bug18037_p2()|
DROP FUNCTION bug18037_f1| DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2| 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 table if exists t3|
drop procedure if exists bug15217| drop procedure if exists bug15217|
create table t3 as select 1| create table t3 as select 1|
......
...@@ -517,7 +517,7 @@ DROP TABLE t12913; ...@@ -517,7 +517,7 @@ DROP TABLE t12913;
create database mysqltest; create database mysqltest;
use mysqltest; use mysqltest;
drop database mysqltest; drop database mysqltest;
--error 1102 --error ER_NO_DB_ERROR
create table test.t1 like x; create table test.t1 like x;
--disable_warnings --disable_warnings
drop table if exists test.t1; drop table if exists test.t1;
......
...@@ -1146,4 +1146,122 @@ execute stmt; ...@@ -1146,4 +1146,122 @@ execute stmt;
execute stmt; execute stmt;
deallocate prepare stmt; deallocate prepare stmt;
drop table t1, t2, t3; 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 # End of 5.0 tests
...@@ -5888,6 +5888,52 @@ DROP FUNCTION bug18037_f1| ...@@ -5888,6 +5888,52 @@ DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2| 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 # 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 # weird error". Check that the code that is supposed to work at
......
...@@ -1667,13 +1667,13 @@ String *Item_func_database::val_str(String *str) ...@@ -1667,13 +1667,13 @@ String *Item_func_database::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
THD *thd= current_thd; THD *thd= current_thd;
if (!thd->db) if (thd->db == NULL)
{ {
null_value= 1; null_value= 1;
return 0; return 0;
} }
else 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; return str;
} }
......
...@@ -1868,9 +1868,10 @@ end: ...@@ -1868,9 +1868,10 @@ end:
don't suffer from these assignments to 0 as DROP TEMPORARY don't suffer from these assignments to 0 as DROP TEMPORARY
TABLE uses the db.table syntax. 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= 0; // just to be sure
thd->query_length= thd->db_length =0; thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd); close_thread_tables(thd);
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
...@@ -2872,7 +2873,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -2872,7 +2873,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
TABLE_LIST tables; TABLE_LIST tables;
bzero((char*) &tables,sizeof(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.alias = tables.table_name = (char*) table_name;
tables.lock_type = TL_WRITE; tables.lock_type = TL_WRITE;
tables.updating= 1; tables.updating= 1;
...@@ -2967,7 +2968,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -2967,7 +2968,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
ex.skip_lines = skip_lines; ex.skip_lines = skip_lines;
List<Item> field_list; List<Item> field_list;
thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables); 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; thd->variables.pseudo_thread_id= thread_id;
List<Item> set_fields; List<Item> set_fields;
if (net) if (net)
...@@ -3014,11 +3015,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -3014,11 +3015,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
error: error:
thd->net.vio = 0; thd->net.vio = 0;
char *save_db= thd->db; const char *remember_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count)); 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= 0;
thd->query_length= thd->db_length= 0; thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd); close_thread_tables(thd);
if (thd->query_error) if (thd->query_error)
...@@ -3035,7 +3037,7 @@ error: ...@@ -3035,7 +3037,7 @@ error:
} }
slave_print_error(rli,sql_errno,"\ slave_print_error(rli,sql_errno,"\
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", 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)); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
return 1; return 1;
} }
...@@ -3045,7 +3047,7 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", ...@@ -3045,7 +3047,7 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
{ {
slave_print_error(rli,ER_UNKNOWN_ERROR, "\ slave_print_error(rli,ER_UNKNOWN_ERROR, "\
Fatal error running LOAD DATA INFILE on table '%s'. Default database: '%s'", 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; return 1;
} }
......
...@@ -1581,9 +1581,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, ...@@ -1581,9 +1581,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 old db in case we are creating in a different database
save_db = thd->db; save_db = thd->db;
save_db_length= thd->db_length; save_db_length= thd->db_length;
thd->db = (char*)db; DBUG_ASSERT(db != 0);
DBUG_ASSERT(thd->db != 0); thd->reset_db((char*)db, strlen(db));
thd->db_length= strlen(thd->db);
mysql_parse(thd, thd->query, packet_len); // run create table mysql_parse(thd, thd->query, packet_len); // run create table
thd->db = save_db; // leave things the way the were before thd->db = save_db; // leave things the way the were before
thd->db_length= save_db_length; thd->db_length= save_db_length;
...@@ -3713,8 +3712,9 @@ err: ...@@ -3713,8 +3712,9 @@ err:
sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s", 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)); IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety thd->query= 0; // extra safety
thd->query_length= thd->db_length= 0; thd->query_length= 0;
thd->reset_db(NULL, 0);
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql) if (mysql)
{ {
...@@ -3932,8 +3932,10 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ ...@@ -3932,8 +3932,10 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
should already have done these assignments (each event which sets these should already have done these assignments (each event which sets these
variables is supposed to set them to 0 before terminating)). variables is supposed to set them to 0 before terminating)).
*/ */
thd->query= thd->db= thd->catalog= 0; thd->catalog= 0;
thd->query_length= thd->db_length= 0; thd->reset_db(NULL, 0);
thd->query= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit"; thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock); pthread_mutex_lock(&rli->run_lock);
......
...@@ -526,10 +526,6 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock, ...@@ -526,10 +526,6 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
MASTER_INFO* mi, MASTER_INFO* mi,
bool high_priority); bool high_priority);
/* If fd is -1, dump to NET */
int mysql_table_dump(THD* thd, const char* db,
const char* tbl_name, int fd = -1);
/* retrieve table from master and copy to slave*/ /* retrieve table from master and copy to slave*/
int fetch_master_table(THD* thd, const char* db_name, const char* table_name, int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
MASTER_INFO* mi, MYSQL* mysql, bool overwrite); MASTER_INFO* mi, MYSQL* mysql, bool overwrite);
......
...@@ -404,7 +404,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ...@@ -404,7 +404,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
{ {
LEX *old_lex= thd->lex, newlex; LEX *old_lex= thd->lex, newlex;
String defstr; 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; bool dbchanged;
ulong old_sql_mode= thd->variables.sql_mode; ulong old_sql_mode= thd->variables.sql_mode;
ha_rows old_select_limit= thd->variables.select_limit; 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, ...@@ -450,9 +451,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
goto end; goto end;
} }
dbchanged= FALSE; if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
1, &dbchanged)))
goto end; goto end;
lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length()); 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, ...@@ -462,14 +461,14 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
{ {
sp_head *sp= newlex.sphead; 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; goto end;
delete sp; delete sp;
ret= SP_PARSE_ERROR; ret= SP_PARSE_ERROR;
} }
else else
{ {
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
goto end; goto end;
*sphp= newlex.sphead; *sphp= newlex.sphead;
(*sphp)->set_definer(&definer_user_name, &definer_host_name); (*sphp)->set_definer(&definer_user_name, &definer_host_name);
...@@ -505,15 +504,14 @@ db_create_routine(THD *thd, int type, sp_head *sp) ...@@ -505,15 +504,14 @@ db_create_routine(THD *thd, int type, sp_head *sp)
int ret; int ret;
TABLE *table; TABLE *table;
char definer[USER_HOST_BUFF_SIZE]; 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; bool dbchanged;
DBUG_ENTER("db_create_routine"); DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length, DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
sp->m_name.str)); sp->m_name.str));
dbchanged= FALSE; if ((ret= sp_use_new_db(thd, sp->m_db, &old_db, 0, &dbchanged)))
if ((ret= sp_use_new_db(thd, sp->m_db.str, olddb, sizeof(olddb),
0, &dbchanged)))
{ {
ret= SP_NO_DB_ERROR; ret= SP_NO_DB_ERROR;
goto done; goto done;
...@@ -641,7 +639,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) ...@@ -641,7 +639,7 @@ db_create_routine(THD *thd, int type, sp_head *sp)
done: done:
close_thread_tables(thd); close_thread_tables(thd);
if (dbchanged) if (dbchanged)
(void)mysql_change_db(thd, olddb, 1); (void) mysql_change_db(thd, old_db.str, 1);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -1814,49 +1812,76 @@ create_string(THD *thd, String *buf, ...@@ -1814,49 +1812,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 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 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_ENTER("sp_use_new_db");
DBUG_PRINT("enter", ("newdb: %s", newdb)); DBUG_PRINT("enter", ("newdb: %s", new_db.str));
if (! newdb) /*
newdb= (char *)""; Set new_db to an empty string if it's NULL, because mysql_change_db
if (thd->db && thd->db[0]) requires a non-NULL argument.
{ new_db.str can be NULL only if we're restoring the old database after
if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0) execution of a stored procedure and there were no current database
changeit= 0; selected. The stored procedure itself must always have its database
else initialized.
*/
if (new_db.str == NULL)
new_db.str= empty_c_string;
if (thd->db)
{ {
changeit= 1; old_db->length= (strmake(old_db->str, thd->db, old_db->length) -
strnmov(olddb, thd->db, olddblen); old_db->str);
} }
}
else
{ // thd->db empty
if (newdb[0])
changeit= 1;
else 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; *dbchangedp= FALSE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
else
{
int ret= mysql_change_db(thd, newdb, no_access_check);
if (! ret) ret= mysql_change_db(thd, new_db.str, no_access_check);
*dbchangedp= TRUE;
*dbchangedp= ret == 0;
DBUG_RETURN(ret); DBUG_RETURN(ret);
}
} }
...@@ -104,15 +104,15 @@ extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); ...@@ -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); TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup);
void close_proc_table(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. Do a "use new_db". The current db is stored at old_db. If new_db is the
// dbchangedp is set to true if the db was actually changed. same as the current one, nothing is changed. dbchangedp is set to true if
the db was actually changed.
*/
int 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); bool no_access_check, bool *dbchangedp);
#endif /* _SP_H_ */ #endif /* _SP_H_ */
...@@ -376,24 +376,6 @@ sp_name::init_qname(THD *thd) ...@@ -376,24 +376,6 @@ sp_name::init_qname(THD *thd)
m_name.length, m_name.str); 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' Check that the name 'ident' is ok. It's assumed to be an 'ident'
...@@ -504,13 +486,12 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -504,13 +486,12 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
/* During parsing, we must use thd->mem_root */ /* During parsing, we must use thd->mem_root */
MEM_ROOT *root= thd->mem_root; MEM_ROOT *root= thd->mem_root;
DBUG_ASSERT(name);
/* Must be initialized in the parser */
DBUG_ASSERT(name->m_db.str && name->m_db.length);
/* We have to copy strings to get them into the right memroot */ /* We have to copy strings to get them into the right memroot */
if (name)
{
m_db.length= name->m_db.length; 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_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
m_name.length= name->m_name.length; m_name.length= name->m_name.length;
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length); m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
...@@ -519,12 +500,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -519,12 +500,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
name->init_qname(thd); name->init_qname(thd);
m_qname.length= name->m_qname.length; m_qname.length= name->m_qname.length;
m_qname.str= strmake_root(root, name->m_qname.str, 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);
}
if (m_param_begin && m_param_end) if (m_param_begin && m_param_end)
{ {
...@@ -933,7 +908,8 @@ bool ...@@ -933,7 +908,8 @@ bool
sp_head::execute(THD *thd) sp_head::execute(THD *thd)
{ {
DBUG_ENTER("sp_head::execute"); 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; bool dbchanged;
sp_rcontext *ctx; sp_rcontext *ctx;
bool err_status= FALSE; bool err_status= FALSE;
...@@ -980,10 +956,8 @@ sp_head::execute(THD *thd) ...@@ -980,10 +956,8 @@ sp_head::execute(THD *thd)
m_first_instance->m_last_cached_sp == this) || m_first_instance->m_last_cached_sp == this) ||
(m_recursion_level + 1 == m_next_cached_sp->m_recursion_level)); (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
dbchanged= FALSE;
if (m_db.length && if (m_db.length &&
(err_status= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, (err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
&dbchanged)))
goto done; goto done;
if ((ctx= thd->spcont)) if ((ctx= thd->spcont))
...@@ -1154,10 +1128,10 @@ sp_head::execute(THD *thd) ...@@ -1154,10 +1128,10 @@ sp_head::execute(THD *thd)
{ {
/* /*
No access check when changing back to where we came from. 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) 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; m_flags&= ~IS_INVOKED;
DBUG_PRINT("info", DBUG_PRINT("info",
...@@ -1815,9 +1789,6 @@ sp_head::reset_thd_mem_root(THD *thd) ...@@ -1815,9 +1789,6 @@ sp_head::reset_thd_mem_root(THD *thd)
(ulong) &mem_root, (ulong) &thd->mem_root)); (ulong) &mem_root, (ulong) &thd->mem_root));
free_list= thd->free_list; // Keep the old list free_list= thd->free_list; // Keep the old list
thd->free_list= NULL; // Start a new one 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; m_thd= thd;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1833,7 +1804,6 @@ sp_head::restore_thd_mem_root(THD *thd) ...@@ -1833,7 +1804,6 @@ sp_head::restore_thd_mem_root(THD *thd)
DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
(ulong) &mem_root, (ulong) &thd->mem_root)); (ulong) &mem_root, (ulong) &thd->mem_root));
thd->free_list= flist; // Restore the old one thd->free_list= flist; // Restore the old one
thd->db= m_thd_db; // Restore the original db pointer
thd->mem_root= m_thd_root; thd->mem_root= m_thd_root;
m_thd= NULL; m_thd= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
......
...@@ -61,13 +61,6 @@ public: ...@@ -61,13 +61,6 @@ public:
*/ */
LEX_STRING m_sroutines_key; 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) sp_name(LEX_STRING db, LEX_STRING name)
: m_db(db), m_name(name) : m_db(db), m_name(name)
{ {
...@@ -101,8 +94,6 @@ public: ...@@ -101,8 +94,6 @@ public:
{} {}
}; };
sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name);
bool bool
check_routine_name(LEX_STRING name); check_routine_name(LEX_STRING name);
...@@ -355,7 +346,6 @@ private: ...@@ -355,7 +346,6 @@ private:
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
THD *m_thd; // Set if we have reset 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 sp_pcontext *m_pcont; // Parse context
List<LEX> m_lex; // Temp. store for the other lex List<LEX> m_lex; // Temp. store for the other lex
......
...@@ -1571,6 +1571,47 @@ public: ...@@ -1571,6 +1571,47 @@ public:
void restore_sub_statement_state(Sub_statement_state *backup); void restore_sub_statement_state(Sub_statement_state *backup);
void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
void restore_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup);
/*
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_strdup_with_length(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;
}
}; };
...@@ -1916,7 +1957,7 @@ typedef struct st_sort_buffer { ...@@ -1916,7 +1957,7 @@ typedef struct st_sort_buffer {
class Table_ident :public Sql_alloc class Table_ident :public Sql_alloc
{ {
public: public:
LEX_STRING db; LEX_STRING db;
LEX_STRING table; LEX_STRING table;
SELECT_LEX_UNIT *sel; SELECT_LEX_UNIT *sel;
......
...@@ -805,8 +805,7 @@ exit: ...@@ -805,8 +805,7 @@ exit:
{ {
if (!(thd->slave_thread)) /* a slave thread will free it itself */ if (!(thd->slave_thread)) /* a slave thread will free it itself */
x_free(thd->db); x_free(thd->db);
thd->db= 0; thd->reset_db(NULL, 0);
thd->db_length= 0;
} }
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
...@@ -1218,14 +1217,10 @@ end: ...@@ -1218,14 +1217,10 @@ end:
{ {
if (!(thd->slave_thread)) if (!(thd->slave_thread))
my_free(dbname, MYF(0)); my_free(dbname, MYF(0));
thd->db= NULL; thd->reset_db(NULL, 0);
thd->db_length= 0;
} }
else else
{ thd->reset_db(dbname, db_length); // THD::~THD will free this
thd->db= dbname; // THD::~THD will free this
thd->db_length= db_length;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!no_access_check) if (!no_access_check)
sctx->db_access= db_access; sctx->db_access= db_access;
......
...@@ -298,9 +298,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -298,9 +298,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
{ {
if (thd->locked_tables) if (thd->locked_tables)
{ {
if (find_locked_table(thd, DBUG_ASSERT(table_list->db); /* Must be set in the parser */
table_list->db ? table_list->db : thd->db, if (find_locked_table(thd, table_list->db, table_list->table_name))
table_list->table_name))
{ {
my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0), my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
table_list->table_name); table_list->table_name);
...@@ -1329,8 +1328,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -1329,8 +1328,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
TABLE *table; TABLE *table;
DBUG_ENTER("delayed_get_table"); DBUG_ENTER("delayed_get_table");
if (!table_list->db) /* Must be set in the parser */
table_list->db=thd->db; DBUG_ASSERT(table_list->db);
/* Find the thread which handles this table. */ /* Find the thread which handles this table. */
if (!(tmp=find_handler(thd,table_list))) if (!(tmp=find_handler(thd,table_list)))
...@@ -1369,15 +1368,15 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -1369,15 +1368,15 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thread_count++; thread_count++;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
if (!(tmp->thd.db=my_strdup(table_list->db,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)))) tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME));
if (tmp->thd.db == NULL || tmp->thd.query == NULL)
{ {
delete tmp; delete tmp;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
goto err1; goto err1;
} }
tmp->table_list= *table_list; // Needed to open table 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->table_list.alias= tmp->table_list.table_name= tmp->thd.query;
tmp->lock(); tmp->lock();
pthread_mutex_lock(&tmp->mutex); pthread_mutex_lock(&tmp->mutex);
......
...@@ -758,6 +758,11 @@ public: ...@@ -758,6 +758,11 @@ public:
*this= *state; *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) void add_to_query_tables(TABLE_LIST *table)
{ {
*(table->prev_global= query_tables_last)= table; *(table->prev_global= query_tables_last)= table;
......
This diff is collapsed.
...@@ -2687,7 +2687,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -2687,7 +2687,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST src_tables_list; TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table"); DBUG_ENTER("mysql_create_like_table");
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 Validate the source table
......
...@@ -932,8 +932,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, ...@@ -932,8 +932,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
save_db.str= thd->db; save_db.str= thd->db;
save_db.length= thd->db_length; save_db.length= thd->db_length;
thd->db_length= strlen(db); thd->reset_db((char*) db, strlen(db));
thd->db= (char *) db;
while ((trg_create_str= it++)) while ((trg_create_str= it++))
{ {
trg_sql_mode= itm++; trg_sql_mode= itm++;
...@@ -1035,8 +1034,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, ...@@ -1035,8 +1034,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
lex_end(&lex); lex_end(&lex);
} }
thd->db= save_db.str; thd->reset_db(save_db.str, save_db.length);
thd->db_length= save_db.length;
thd->lex= old_lex; thd->lex= old_lex;
thd->spcont= save_spcont; thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode; thd->variables.sql_mode= save_sql_mode;
...@@ -1049,8 +1047,7 @@ err_with_lex_cleanup: ...@@ -1049,8 +1047,7 @@ err_with_lex_cleanup:
thd->lex= old_lex; thd->lex= old_lex;
thd->spcont= save_spcont; thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode; thd->variables.sql_mode= save_sql_mode;
thd->db= save_db.str; thd->reset_db(save_db.str, save_db.length);
thd->db_length= save_db.length;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -140,6 +140,7 @@ void udf_init() ...@@ -140,6 +140,7 @@ void udf_init()
READ_RECORD read_record_info; READ_RECORD read_record_info;
TABLE *table; TABLE *table;
int error; int error;
char db[]= "mysql"; /* A subject to casednstr, can't be constant */
DBUG_ENTER("ufd_init"); DBUG_ENTER("ufd_init");
if (initialized) if (initialized)
...@@ -161,13 +162,12 @@ void udf_init() ...@@ -161,13 +162,12 @@ void udf_init()
initialized = 1; initialized = 1;
new_thd->thread_stack= (char*) &new_thd; new_thd->thread_stack= (char*) &new_thd;
new_thd->store_globals(); new_thd->store_globals();
new_thd->db= my_strdup("mysql", MYF(0)); new_thd->set_db(db, sizeof(db)-1);
new_thd->db_length=5;
bzero((gptr) &tables,sizeof(tables)); bzero((gptr) &tables,sizeof(tables));
tables.alias= tables.table_name= (char*) "func"; tables.alias= tables.table_name= (char*) "func";
tables.lock_type = TL_READ; tables.lock_type = TL_READ;
tables.db=new_thd->db; tables.db= db;
if (simple_open_n_lock_tables(new_thd, &tables)) if (simple_open_n_lock_tables(new_thd, &tables))
{ {
......
...@@ -452,15 +452,15 @@ bool mysql_create_view(THD *thd, ...@@ -452,15 +452,15 @@ bool mysql_create_view(THD *thd,
*/ */
for (sl= select_lex; sl; sl= sl->next_select()) 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); List_iterator_fast<Item> it(sl->item_list);
Item *item; Item *item;
fill_effective_table_privileges(thd, &view->grant, db, fill_effective_table_privileges(thd, &view->grant, view->db,
view->table_name); view->table_name);
while ((item= it++)) while ((item= it++))
{ {
Item_field *fld; 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->table_name, item->name) &
VIEW_ANY_ACL); VIEW_ANY_ACL);
if ((fld= item->filed_for_view_update())) if ((fld= item->filed_for_view_update()))
...@@ -641,8 +641,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ...@@ -641,8 +641,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
if (!parser->ok() || !is_equal(&view_type, parser->type())) if (!parser->ok() || !is_equal(&view_type, parser->type()))
{ {
my_error(ER_WRONG_OBJECT, MYF(0), my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
(view->db ? view->db : thd->db), view->table_name, "VIEW");
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
......
...@@ -1237,12 +1237,18 @@ sp_name: ...@@ -1237,12 +1237,18 @@ sp_name:
} }
| ident | ident
{ {
THD *thd= YYTHD;
LEX_STRING db;
if (check_routine_name($1)) if (check_routine_name($1))
{ {
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
YYABORT; 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);
} }
; ;
...@@ -2405,14 +2411,26 @@ create2: ...@@ -2405,14 +2411,26 @@ create2:
| LIKE table_ident | LIKE table_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
THD *thd= lex->thd;
if (!(lex->name= (char *)$2)) if (!(lex->name= (char *)$2))
YYABORT; YYABORT;
if ($2->db.str == NULL &&
thd->copy_db_to(&($2->db.str), &($2->db.length)))
{
YYABORT;
}
} }
| '(' LIKE table_ident ')' | '(' LIKE table_ident ')'
{ {
LEX *lex=Lex; LEX *lex=Lex;
THD *thd= lex->thd;
if (!(lex->name= (char *)$3)) if (!(lex->name= (char *)$3))
YYABORT; YYABORT;
if ($3->db.str == NULL &&
thd->copy_db_to(&($3->db.str), &($3->db.length)))
{
YYABORT;
}
} }
; ;
...@@ -3240,7 +3258,9 @@ alter: ...@@ -3240,7 +3258,9 @@ alter:
lex->key_list.empty(); lex->key_list.empty();
lex->col_list.empty(); lex->col_list.empty();
lex->select_lex.init_order(); lex->select_lex.init_order();
lex->select_lex.db=lex->name=0; lex->select_lex.db=
((TABLE_LIST*) lex->select_lex.table_list.first)->db;
lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info)); bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.default_table_charset= NULL; lex->create_info.default_table_charset= NULL;
...@@ -3258,8 +3278,11 @@ alter: ...@@ -3258,8 +3278,11 @@ alter:
opt_create_database_options opt_create_database_options
{ {
LEX *lex=Lex; LEX *lex=Lex;
THD *thd= Lex->thd;
lex->sql_command=SQLCOM_ALTER_DB; lex->sql_command=SQLCOM_ALTER_DB;
lex->name= $3; lex->name= $3;
if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL))
YYABORT;
} }
| ALTER PROCEDURE sp_name | ALTER PROCEDURE sp_name
{ {
...@@ -3421,14 +3444,20 @@ alter_list_item: ...@@ -3421,14 +3444,20 @@ alter_list_item:
| RENAME opt_to table_ident | RENAME opt_to table_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
THD *thd= lex->thd;
lex->select_lex.db=$3->db.str; 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) || if (check_table_name($3->table.str,$3->table.length) ||
$3->db.str && check_db_name($3->db.str)) $3->db.str && check_db_name($3->db.str))
{ {
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str); my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
YYABORT; YYABORT;
} }
lex->name= $3->table.str;
lex->alter_info.flags|= ALTER_RENAME; lex->alter_info.flags|= ALTER_RENAME;
} }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
...@@ -4742,7 +4771,13 @@ simple_expr: ...@@ -4742,7 +4771,13 @@ simple_expr:
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */
{ {
LEX *lex= Lex; 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); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
if ($4) if ($4)
...@@ -8460,7 +8495,9 @@ grant_ident: ...@@ -8460,7 +8495,9 @@ grant_ident:
'*' '*'
{ {
LEX *lex= Lex; 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) if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL; lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements) else if (lex->columns.elements)
......
...@@ -1548,6 +1548,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) ...@@ -1548,6 +1548,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
TABLE *table; TABLE *table;
Tz_names_entry *tmp_tzname; Tz_names_entry *tmp_tzname;
my_bool return_val= 1; my_bool return_val= 1;
char db[]= "mysql";
int res; int res;
DBUG_ENTER("my_tz_init"); DBUG_ENTER("my_tz_init");
...@@ -1604,13 +1605,12 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) ...@@ -1604,13 +1605,12 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
leap seconds shared by all time zones. leap seconds shared by all time zones.
*/ */
thd->db= my_strdup("mysql",MYF(0)); thd->set_db(db, sizeof(db)-1);
thd->db_length= 5; // Safety
bzero((char*) &tables_buff, sizeof(TABLE_LIST)); bzero((char*) &tables_buff, sizeof(TABLE_LIST));
tables_buff[0].alias= tables_buff[0].table_name= tables_buff[0].alias= tables_buff[0].table_name=
(char*)"time_zone_leap_second"; (char*)"time_zone_leap_second";
tables_buff[0].lock_type= TL_READ; 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 Fill TABLE_LIST for the rest of the time zone describing tables
and link it to first one. and link it to first one.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment