Below is the list of changes that have just been committed into a local
5.0 repository of kostja. When kostja does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2200 06/06/27 00:52:56 konstantin@stripped +15 -0
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into mysql.com:/opt/local/work/mysql-5.0-17199
mysql-test/t/sp.test
1.190 06/06/27 00:52:52 konstantin@stripped +0 -0
SCCS merged
mysql-test/r/sp.result
1.202 06/06/27 00:52:52 konstantin@stripped +0 -0
SCCS merged
sql/sql_yacc.yy
1.471 06/06/27 00:50:52 konstantin@stripped +0 -0
Auto merged
sql/sql_table.cc
1.315 06/06/27 00:50:51 konstantin@stripped +0 -0
Auto merged
sql/sql_parse.cc
1.554 06/06/27 00:50:51 konstantin@stripped +0 -0
Auto merged
sql/sql_lex.h
1.219 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/sql_insert.cc
1.193 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/sql_db.cc
1.129 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/sql_class.h
1.290 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/sp_head.cc
1.217 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/slave.cc
1.271 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/log_event.cc
1.206 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
sql/item_strfunc.cc
1.271 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
mysql-test/t/create.test
1.80 06/06/27 00:50:50 konstantin@stripped +0 -0
Auto merged
mysql-test/r/create.result
1.118 06/06/27 00:50:49 konstantin@stripped +0 -0
Auto merged
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: konstantin
# Host: bodhi.netgear
# Root: /opt/local/work/mysql-5.0-17199/RESYNC
--- 1.270/sql/item_strfunc.cc 2006-06-21 07:49:28 +04:00
+++ 1.271/sql/item_strfunc.cc 2006-06-27 00:50:50 +04:00
@@ -1667,13 +1667,13 @@
{
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;
}
--- 1.205/sql/log_event.cc 2006-06-12 16:54:40 +04:00
+++ 1.206/sql/log_event.cc 2006-06-27 00:50:50 +04:00
@@ -1868,9 +1868,10 @@
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));
@@ -2872,7 +2873,7 @@
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;
@@ -2967,7 +2968,7 @@
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)
@@ -3014,11 +3015,12 @@
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)
@@ -3035,7 +3037,7 @@
}
slave_print_error(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;
}
@@ -3045,7 +3047,7 @@
{
slave_print_error(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;
}
--- 1.270/sql/slave.cc 2006-06-20 22:46:39 +04:00
+++ 1.271/sql/slave.cc 2006-06-27 00:50:50 +04:00
@@ -1581,9 +1581,8 @@
// 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;
@@ -3713,8 +3712,9 @@
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)
{
@@ -3932,8 +3932,10 @@
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);
--- 1.289/sql/sql_class.h 2006-06-16 13:05:45 +04:00
+++ 1.290/sql/sql_class.h 2006-06-27 00:50:50 +04:00
@@ -1571,6 +1571,47 @@
void restore_sub_statement_state(Sub_statement_state *backup);
void set_n_backup_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 @@
class Table_ident :public Sql_alloc
{
- public:
+public:
LEX_STRING db;
LEX_STRING table;
SELECT_LEX_UNIT *sel;
--- 1.128/sql/sql_db.cc 2006-05-29 17:26:18 +04:00
+++ 1.129/sql/sql_db.cc 2006-06-27 00:50:50 +04:00
@@ -805,8 +805,7 @@
{
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);
@@ -1218,14 +1217,10 @@
{
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;
--- 1.192/sql/sql_insert.cc 2006-06-19 16:57:36 +04:00
+++ 1.193/sql/sql_insert.cc 2006-06-27 00:50:50 +04:00
@@ -298,9 +298,8 @@
{
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);
@@ -1329,8 +1328,8 @@
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)))
@@ -1369,15 +1368,15 @@
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);
--- 1.218/sql/sql_lex.h 2006-06-17 00:49:13 +04:00
+++ 1.219/sql/sql_lex.h 2006-06-27 00:50:50 +04:00
@@ -758,6 +758,11 @@
*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;
--- 1.553/sql/sql_parse.cc 2006-06-23 16:09:31 +04:00
+++ 1.554/sql/sql_parse.cc 2006-06-27 00:50:51 +04:00
@@ -93,8 +93,6 @@
"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)
{
@@ -300,8 +298,7 @@
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 */
@@ -341,9 +338,8 @@
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
@@ -1316,19 +1312,6 @@
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() */
@@ -1340,7 +1323,26 @@
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;
@@ -1377,7 +1379,7 @@
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:
@@ -1627,7 +1629,7 @@
}
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:
@@ -1801,11 +1803,8 @@
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());
@@ -2152,6 +2151,34 @@
}
+/*
+ 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)
{
@@ -2179,13 +2206,13 @@
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))
{
@@ -2202,11 +2229,6 @@
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
@@ -2739,8 +2761,8 @@
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)))
@@ -2988,25 +3010,8 @@
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, ALTER_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)) ||
@@ -3676,12 +3681,8 @@
}
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), lex->name);
@@ -4130,23 +4131,11 @@
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)))
@@ -4263,41 +4252,27 @@
}
#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))
{
close_thread_tables(thd);
- 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,
ER(ER_PROC_AUTO_GRANT_FAIL));
}
#endif
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
send_ok(thd);
}
else
@@ -4712,7 +4687,8 @@
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);
@@ -5282,7 +5258,7 @@
(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;
@@ -5430,22 +5406,25 @@
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(¤t_db, 0))
+ return TRUE;
+ tables->db= current_db;
}
}
return FALSE;
}
-
/****************************************************************************
Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/
@@ -6065,19 +6044,8 @@
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)
@@ -7268,6 +7236,8 @@
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);
}
--- 1.314/sql/sql_table.cc 2006-06-23 20:15:34 +04:00
+++ 1.315/sql/sql_table.cc 2006-06-27 00:50:51 +04:00
@@ -2687,7 +2687,8 @@
TABLE_LIST src_tables_list;
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
--- 1.470/sql/sql_yacc.yy 2006-06-15 22:09:05 +04:00
+++ 1.471/sql/sql_yacc.yy 2006-06-27 00:50:52 +04:00
@@ -1237,12 +1237,18 @@
}
| 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);
}
;
@@ -2405,14 +2411,26 @@
| LIKE table_ident
{
LEX *lex=Lex;
+ THD *thd= lex->thd;
if (!(lex->name= (char *)$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->name= (char *)$3))
YYABORT;
+ if ($3->db.str == NULL &&
+ thd->copy_db_to(&($3->db.str), &($3->db.length)))
+ {
+ YYABORT;
+ }
}
;
@@ -3240,7 +3258,9 @@
lex->key_list.empty();
lex->col_list.empty();
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));
lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.default_table_charset= NULL;
@@ -3258,8 +3278,11 @@
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
{
@@ -3421,14 +3444,20 @@
| 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
@@ -4742,7 +4771,13 @@
#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)
@@ -8460,7 +8495,9 @@
'*'
{
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)
--- 1.117/mysql-test/r/create.result 2006-06-04 22:27:36 +04:00
+++ 1.118/mysql-test/r/create.result 2006-06-27 00:50:49 +04:00
@@ -607,7 +607,7 @@
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;
--- 1.79/mysql-test/t/create.test 2006-06-04 22:27:36 +04:00
+++ 1.80/mysql-test/t/create.test 2006-06-27 00:50:50 +04:00
@@ -517,7 +517,7 @@
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;
--- 1.201/mysql-test/r/sp.result 2006-06-22 19:29:44 +04:00
+++ 1.202/mysql-test/r/sp.result 2006-06-27 00:52:52 +04:00
@@ -4990,6 +4990,52 @@
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|
--- 1.189/mysql-test/t/sp.test 2006-06-22 19:29:45 +04:00
+++ 1.190/mysql-test/t/sp.test 2006-06-27 00:52:52 +04:00
@@ -5889,6 +5889,52 @@
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
# the first execution of a stored procedure actually works for
--- 1.216/sql/sp_head.cc 2006-06-26 06:48:10 +04:00
+++ 1.217/sql/sp_head.cc 2006-06-27 00:50:50 +04:00
@@ -376,24 +376,6 @@
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'
@@ -504,27 +486,20 @@
/* During parsing, we must use 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 */
- 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);
-
- 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);
- }
+ 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)
{
@@ -933,7 +908,8 @@
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;
@@ -980,10 +956,8 @@
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))
@@ -1154,10 +1128,10 @@
{
/*
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",
@@ -1815,9 +1789,6 @@
(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;
}
@@ -1833,7 +1804,6 @@
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;
| Thread |
|---|
| • bk commit into 5.0 tree (konstantin:1.2200) | konstantin | 26 Jun |