Commit f9759397 authored by unknown's avatar unknown

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

into  damien-katzs-computer.local:/Users/dkatz/mysql-5.0-runtime

parents c986d919 77c50858
...@@ -1452,3 +1452,16 @@ end ...@@ -1452,3 +1452,16 @@ end
until true end repeat retry; until true end repeat retry;
end// end//
ERROR 42000: LEAVE with no matching label: retry ERROR 42000: LEAVE with no matching label: retry
DROP DATABASE IF EXISTS mysqltest;
CREATE DATABASE mysqltest;
USE mysqltest;
DROP DATABASE mysqltest;
SELECT inexistent(), 1 + ,;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
SELECT inexistent();
ERROR 42000: FUNCTION inexistent does not exist
SELECT .inexistent();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '()' at line 1
SELECT ..inexistent();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.inexistent()' at line 1
USE test;
...@@ -5667,7 +5667,6 @@ t3_id_1 t3_id_2 t4_id ...@@ -5667,7 +5667,6 @@ t3_id_1 t3_id_2 t4_id
DROP PROCEDURE p1| DROP PROCEDURE p1|
DROP VIEW v1, v2| DROP VIEW v1, v2|
DROP TABLE t3, t4| DROP TABLE t3, t4|
End of 5.0 tests
DROP TABLE IF EXISTS bug23760| DROP TABLE IF EXISTS bug23760|
DROP TABLE IF EXISTS bug23760_log| DROP TABLE IF EXISTS bug23760_log|
DROP PROCEDURE IF EXISTS bug23760_update_log| DROP PROCEDURE IF EXISTS bug23760_update_log|
...@@ -6145,7 +6144,6 @@ Procedure sql_mode Create Procedure ...@@ -6145,7 +6144,6 @@ Procedure sql_mode Create Procedure
proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`() proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`()
`my_label`:BEGIN END `my_label`:BEGIN END
drop procedure proc_21513| drop procedure proc_21513|
End of 5.0 tests.
drop table t1,t2; drop table t1,t2;
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
...@@ -6565,4 +6563,6 @@ f1() ...@@ -6565,4 +6563,6 @@ f1()
DROP TABLE t1; DROP TABLE t1;
DROP FUNCTION f1; DROP FUNCTION f1;
End of 5.0 tests # ------------------------------------------------------------------
# -- End of 5.0 tests
# ------------------------------------------------------------------
...@@ -296,4 +296,11 @@ Qcache_queries_in_cache 0 ...@@ -296,4 +296,11 @@ Qcache_queries_in_cache 0
drop table t1; drop table t1;
drop function metaphon; drop function metaphon;
set GLOBAL query_cache_size=default; set GLOBAL query_cache_size=default;
DROP DATABASE IF EXISTS mysqltest;
CREATE DATABASE mysqltest;
USE mysqltest;
DROP DATABASE mysqltest;
CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
DROP FUNCTION metaphon;
USE test;
End of 5.0 tests. End of 5.0 tests.
...@@ -2089,6 +2089,26 @@ end// ...@@ -2089,6 +2089,26 @@ end//
delimiter ;// delimiter ;//
#
# Bug#29816 Syntactically wrong query fails with misleading error message
#
--disable_warnings
DROP DATABASE IF EXISTS mysqltest;
--enable_warnings
CREATE DATABASE mysqltest;
USE mysqltest;
DROP DATABASE mysqltest;
--error ER_PARSE_ERROR
SELECT inexistent(), 1 + ,;
--error ER_SP_DOES_NOT_EXIST
SELECT inexistent();
--error ER_PARSE_ERROR
SELECT .inexistent();
--error ER_PARSE_ERROR
SELECT ..inexistent();
USE test;
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -6642,9 +6642,6 @@ DROP VIEW v1, v2| ...@@ -6642,9 +6642,6 @@ DROP VIEW v1, v2|
DROP TABLE t3, t4| DROP TABLE t3, t4|
--echo End of 5.0 tests
# #
# BUG#23760: ROW_COUNT() and store procedure not owrking together # BUG#23760: ROW_COUNT() and store procedure not owrking together
# #
...@@ -7076,9 +7073,6 @@ show create procedure proc_21513| ...@@ -7076,9 +7073,6 @@ show create procedure proc_21513|
drop procedure proc_21513| drop procedure proc_21513|
###
--echo End of 5.0 tests.
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
...@@ -7677,4 +7671,6 @@ DROP FUNCTION f1; ...@@ -7677,4 +7671,6 @@ DROP FUNCTION f1;
########################################################################### ###########################################################################
--echo End of 5.0 tests --echo # ------------------------------------------------------------------
--echo # -- End of 5.0 tests
--echo # ------------------------------------------------------------------
...@@ -311,5 +311,19 @@ drop table t1; ...@@ -311,5 +311,19 @@ drop table t1;
drop function metaphon; drop function metaphon;
set GLOBAL query_cache_size=default; set GLOBAL query_cache_size=default;
#
# Bug#28318 CREATE FUNCTION (UDF) requires a schema
#
--disable_warnings
DROP DATABASE IF EXISTS mysqltest;
--enable_warnings
CREATE DATABASE mysqltest;
USE mysqltest;
DROP DATABASE mysqltest;
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
DROP FUNCTION metaphon;
USE test;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -1405,12 +1405,12 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, ...@@ -1405,12 +1405,12 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
{ {
Sroutine_hash_entry *rn= Sroutine_hash_entry *rn=
(Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) + (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
key->length); key->length + 1);
if (!rn) // OOM. Error will be reported using fatal_error(). if (!rn) // OOM. Error will be reported using fatal_error().
return FALSE; return FALSE;
rn->key.length= key->length; rn->key.length= key->length;
rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
memcpy(rn->key.str, key->str, key->length); memcpy(rn->key.str, key->str, key->length + 1);
my_hash_insert(&lex->sroutines, (byte *)rn); my_hash_insert(&lex->sroutines, (byte *)rn);
lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next);
rn->belong_to_view= belong_to_view; rn->belong_to_view= belong_to_view;
...@@ -1595,7 +1595,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1595,7 +1595,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
for (Sroutine_hash_entry *rt= start; rt; rt= rt->next) for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
{ {
sp_name name(rt->key.str, rt->key.length); sp_name name(thd, rt->key.str, rt->key.length);
int type= rt->key.str[0]; int type= rt->key.str[0];
sp_head *sp; sp_head *sp;
...@@ -1603,13 +1603,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1603,13 +1603,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
&thd->sp_func_cache : &thd->sp_proc_cache), &thd->sp_func_cache : &thd->sp_proc_cache),
&name))) &name)))
{ {
name.m_name.str= strchr(name.m_qname.str, '.');
name.m_db.length= name.m_name.str - name.m_qname.str;
name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str,
name.m_db.length);
name.m_name.str+= 1;
name.m_name.length= name.m_qname.length - name.m_db.length - 1;
switch ((ret= db_find_routine(thd, type, &name, &sp))) switch ((ret= db_find_routine(thd, type, &name, &sp)))
{ {
case SP_OK: case SP_OK:
......
...@@ -369,17 +369,42 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) ...@@ -369,17 +369,42 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
* *
*/ */
sp_name::sp_name(THD *thd, char *key, uint key_len)
{
m_sroutines_key.str= key;
m_sroutines_key.length= key_len;
m_qname.str= ++key;
m_qname.length= key_len - 1;
if ((m_name.str= strchr(m_qname.str, '.')))
{
m_db.length= m_name.str - key;
m_db.str= strmake_root(thd->mem_root, key, m_db.length);
m_name.str++;
m_name.length= m_qname.length - m_db.length - 1;
}
else
{
m_name.str= m_qname.str;
m_name.length= m_qname.length;
m_db.str= 0;
m_db.length= 0;
}
m_explicit_name= false;
}
void void
sp_name::init_qname(THD *thd) sp_name::init_qname(THD *thd)
{ {
m_sroutines_key.length= m_db.length + m_name.length + 2; const uint dot= !!m_db.length;
/* m_sroutines format: m_type + [database + dot] + name + nul */
m_sroutines_key.length= 1 + m_db.length + dot + m_name.length;
if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1))) if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1)))
return; return;
m_qname.length= m_sroutines_key.length - 1; m_qname.length= m_sroutines_key.length - 1;
m_qname.str= m_sroutines_key.str + 1; m_qname.str= m_sroutines_key.str + 1;
sprintf(m_qname.str, "%.*s.%.*s", sprintf(m_qname.str, "%.*s%.*s%.*s",
m_db.length, (m_db.length ? m_db.str : ""), m_db.length, (m_db.length ? m_db.str : ""),
m_name.length, m_name.str); dot, ".", m_name.length, m_name.str);
} }
......
...@@ -72,16 +72,7 @@ public: ...@@ -72,16 +72,7 @@ public:
Creates temporary sp_name object from key, used mainly Creates temporary sp_name object from key, used mainly
for SP-cache lookups. for SP-cache lookups.
*/ */
sp_name(char *key, uint key_len) sp_name(THD *thd, char *key, uint key_len);
{
m_sroutines_key.str= key;
m_sroutines_key.length= key_len;
m_name.str= m_qname.str= key + 1;
m_name.length= m_qname.length= key_len - 1;
m_db.str= 0;
m_db.length= 0;
m_explicit_name= false;
}
// Init. the qualified name from the db and name. // Init. the qualified name from the db and name.
void init_qname(THD *thd); // thd for memroot allocation void init_qname(THD *thd); // thd for memroot allocation
......
...@@ -1745,7 +1745,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -1745,7 +1745,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* close handler tables which are marked for flush */ /*
In order for the back off and re-start process to work properly,
handler tables having old versions (due to FLUSH TABLES or pending
name-lock) MUST be closed. This is specially important if a name-lock
is pending for any table of the handler_tables list, otherwise a
deadlock may occur.
*/
if (thd->handler_tables) if (thd->handler_tables)
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
...@@ -1810,6 +1816,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -1810,6 +1816,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->db_stat == 0 signals wait_for_locked_table_names table->db_stat == 0 signals wait_for_locked_table_names
that the tables in question are not used any more. See that the tables in question are not used any more. See
table_is_used call for details. table_is_used call for details.
Notice that HANDLER tables were already taken care of by
the earlier call to mysql_ha_flush() in this same critical
section.
*/ */
close_old_data_files(thd,thd->open_tables,0,0); close_old_data_files(thd,thd->open_tables,0,0);
/* /*
......
...@@ -182,7 +182,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) ...@@ -182,7 +182,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
char *db, *name, *alias; char *db, *name, *alias;
uint dblen, namelen, aliaslen, counter; uint dblen, namelen, aliaslen, counter;
int error; int error;
TABLE *backup_open_tables, *backup_handler_tables; TABLE *backup_open_tables;
DBUG_ENTER("mysql_ha_open"); DBUG_ENTER("mysql_ha_open");
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d", DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
tables->db, tables->table_name, tables->alias, tables->db, tables->table_name, tables->alias,
...@@ -211,14 +211,20 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) ...@@ -211,14 +211,20 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
} }
} }
/* save open_ and handler_ tables state */ /*
backup_open_tables= thd->open_tables; Save and reset the open_tables list so that open_tables() won't
backup_handler_tables= thd->handler_tables; be able to access (or know about) the previous list. And on return
from open_tables(), thd->open_tables will contain only the opened
table.
The thd->handler_tables list is kept as-is to avoid deadlocks if
open_table(), called by open_tables(), needs to back-off because
of a pending name-lock on the table being opened.
/* no pre-opened tables */ See open_table() back-off comments for more details.
*/
backup_open_tables= thd->open_tables;
thd->open_tables= NULL; thd->open_tables= NULL;
/* to avoid flushes */
thd->handler_tables= NULL;
/* /*
open_tables() will set 'tables->table' if successful. open_tables() will set 'tables->table' if successful.
...@@ -231,9 +237,12 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) ...@@ -231,9 +237,12 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
error= open_tables(thd, &tables, &counter, 0); error= open_tables(thd, &tables, &counter, 0);
/* restore the state and merge the opened table into handler_tables list */ /* restore the state and merge the opened table into handler_tables list */
thd->handler_tables= thd->open_tables ? if (thd->open_tables)
thd->open_tables->next= backup_handler_tables, {
thd->open_tables : backup_handler_tables; thd->open_tables->next= thd->handler_tables;
thd->handler_tables= thd->open_tables;
}
thd->open_tables= backup_open_tables; thd->open_tables= backup_open_tables;
if (error) if (error)
...@@ -360,7 +369,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -360,7 +369,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit_cnt, ha_rows offset_limit_cnt) ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{ {
TABLE_LIST *hash_tables; TABLE_LIST *hash_tables;
TABLE *table, *backup_open_tables, *backup_handler_tables; TABLE *table, *backup_open_tables;
MYSQL_LOCK *lock; MYSQL_LOCK *lock;
List<Item> list; List<Item> list;
Protocol *protocol= thd->protocol; Protocol *protocol= thd->protocol;
...@@ -437,20 +446,20 @@ retry: ...@@ -437,20 +446,20 @@ retry:
} }
tables->table=table; tables->table=table;
/* save open_ and handler_ tables state */ /* save open_tables state */
backup_open_tables= thd->open_tables; backup_open_tables= thd->open_tables;
backup_handler_tables= thd->handler_tables; /*
mysql_lock_tables() needs thd->open_tables to be set correctly to
/* no pre-opened tables */ be able to handle aborts properly. When the abort happens, it's
thd->open_tables= NULL; safe to not protect thd->handler_tables because it won't close any
/* to avoid flushes */ tables.
thd->handler_tables= NULL; */
thd->open_tables= thd->handler_tables;
lock= mysql_lock_tables(thd, &tables->table, 1, lock= mysql_lock_tables(thd, &tables->table, 1,
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen); MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen);
/* restore previous context */ /* restore previous context */
thd->handler_tables= backup_handler_tables;
thd->open_tables= backup_open_tables; thd->open_tables= backup_open_tables;
if (need_reopen) if (need_reopen)
......
...@@ -1570,13 +1570,15 @@ sp_name: ...@@ -1570,13 +1570,15 @@ sp_name:
| ident | ident
{ {
LEX *lex= Lex; LEX *lex= Lex;
LEX_STRING db; LEX_STRING db= {0,0};
THD *thd= YYTHD;
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);
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (lex->copy_db_to(&db.str, &db.length)) if (thd->db && thd->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT; MYSQL_YYABORT;
$$= new sp_name(db, $1, false); $$= new sp_name(db, $1, false);
if ($$) if ($$)
...@@ -1626,6 +1628,13 @@ create_function_tail: ...@@ -1626,6 +1628,13 @@ create_function_tail:
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"); my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (!lex->spname->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
sp->reset_thd_mem_root(thd); sp->reset_thd_mem_root(thd);
...@@ -5195,8 +5204,8 @@ simple_expr: ...@@ -5195,8 +5204,8 @@ simple_expr:
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */
{ {
THD *thd= lex->thd; THD *thd= lex->thd;
LEX_STRING db; LEX_STRING db= {0,0};
if (lex->copy_db_to(&db.str, &db.length)) if (thd->db && thd->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT; MYSQL_YYABORT;
sp_name *name= new sp_name(db, $1, false); sp_name *name= new sp_name(db, $1, false);
if (name) if (name)
...@@ -9745,7 +9754,13 @@ trigger_tail: ...@@ -9745,7 +9754,13 @@ trigger_tail:
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (!$3->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
if (!(sp= new sp_head())) if (!(sp= new sp_head()))
MYSQL_YYABORT; MYSQL_YYABORT;
sp->reset_thd_mem_root(thd); sp->reset_thd_mem_root(thd);
...@@ -9828,6 +9843,12 @@ sp_tail: ...@@ -9828,6 +9843,12 @@ sp_tail:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
if (!$3->m_db.length)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
MYSQL_YYABORT;
}
lex->stmt_definition_begin= $2; lex->stmt_definition_begin= $2;
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
......
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