diff options
author | unknown <dkatz@damien-katzs-computer.local> | 2007-10-10 14:46:30 -0400 |
---|---|---|
committer | unknown <dkatz@damien-katzs-computer.local> | 2007-10-10 14:46:30 -0400 |
commit | f9759397d251b06a08a86c343ee5912650af2f0c (patch) | |
tree | 34fc19150b115d38b54ac8187d732744d868ba81 | |
parent | c986d919c639a16feaa138ef6d3f8b7cf7e75baa (diff) | |
parent | 77c50858822197afd1b50e34c65954fd9bf6931b (diff) | |
download | mariadb-git-f9759397d251b06a08a86c343ee5912650af2f0c.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into damien-katzs-computer.local:/Users/dkatz/mysql-5.0-runtime
-rw-r--r-- | mysql-test/r/sp-error.result | 13 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 6 | ||||
-rw-r--r-- | mysql-test/r/udf.result | 7 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 20 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 10 | ||||
-rw-r--r-- | mysql-test/t/udf.test | 14 | ||||
-rw-r--r-- | sql/sp.cc | 13 | ||||
-rw-r--r-- | sql/sp_head.cc | 31 | ||||
-rw-r--r-- | sql/sp_head.h | 11 | ||||
-rw-r--r-- | sql/sql_base.cc | 12 | ||||
-rw-r--r-- | sql/sql_handler.cc | 47 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 31 |
12 files changed, 157 insertions, 58 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index bd0640b2b14..cc217ecd093 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1452,3 +1452,16 @@ end until true end repeat retry; end// 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; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b1120a22dfd..ef173b9661f 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5667,7 +5667,6 @@ t3_id_1 t3_id_2 t4_id DROP PROCEDURE p1| DROP VIEW v1, v2| DROP TABLE t3, t4| -End of 5.0 tests DROP TABLE IF EXISTS bug23760| DROP TABLE IF EXISTS bug23760_log| DROP PROCEDURE IF EXISTS bug23760_update_log| @@ -6145,7 +6144,6 @@ Procedure sql_mode Create Procedure proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`() `my_label`:BEGIN END drop procedure proc_21513| -End of 5.0 tests. drop table t1,t2; CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; @@ -6565,4 +6563,6 @@ f1() DROP TABLE t1; DROP FUNCTION f1; -End of 5.0 tests +# ------------------------------------------------------------------ +# -- End of 5.0 tests +# ------------------------------------------------------------------ diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 2e9cf217ed6..3e29c780ca8 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -296,4 +296,11 @@ Qcache_queries_in_cache 0 drop table t1; drop function metaphon; 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. diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 240cda67edc..a1abf4852b0 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2090,6 +2090,26 @@ end// 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 # #--disable_warnings diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 465585a693e..501d96c842a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6642,9 +6642,6 @@ DROP VIEW v1, v2| DROP TABLE t3, t4| ---echo End of 5.0 tests - - # # BUG#23760: ROW_COUNT() and store procedure not owrking together # @@ -7076,9 +7073,6 @@ show create procedure proc_21513| drop procedure proc_21513| -### ---echo End of 5.0 tests. - # # BUG#NNNN: New bug synopsis # @@ -7677,4 +7671,6 @@ DROP FUNCTION f1; ########################################################################### ---echo End of 5.0 tests +--echo # ------------------------------------------------------------------ +--echo # -- End of 5.0 tests +--echo # ------------------------------------------------------------------ diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 75af1f4be4b..6a516a29534 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -311,5 +311,19 @@ drop table t1; drop function metaphon; 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. diff --git a/sql/sp.cc b/sql/sp.cc index 75d6fa4618f..0b84e1ad07f 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1405,12 +1405,12 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, { Sroutine_hash_entry *rn= (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) + - key->length); + key->length + 1); if (!rn) // OOM. Error will be reported using fatal_error(). return FALSE; rn->key.length= key->length; 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); lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); rn->belong_to_view= belong_to_view; @@ -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) { - 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]; sp_head *sp; @@ -1603,13 +1603,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, &thd->sp_func_cache : &thd->sp_proc_cache), &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))) { case SP_OK: diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5ad6625efb8..69dda9ec1e8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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 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))) return; m_qname.length= m_sroutines_key.length - 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_name.length, m_name.str); + dot, ".", m_name.length, m_name.str); } diff --git a/sql/sp_head.h b/sql/sp_head.h index ebe40ce9c87..7d042367985 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -72,16 +72,7 @@ public: Creates temporary sp_name object from key, used mainly for SP-cache lookups. */ - sp_name(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; - } + sp_name(THD *thd, char *key, uint key_len); // Init. the qualified name from the db and name. void init_qname(THD *thd); // thd for memroot allocation diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 289924ff418..905190cb9cd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1745,7 +1745,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, 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) 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, table->db_stat == 0 signals wait_for_locked_table_names that the tables in question are not used any more. See 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); /* diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 89090c9fa63..e87381dd49c 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -182,7 +182,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) char *db, *name, *alias; uint dblen, namelen, aliaslen, counter; int error; - TABLE *backup_open_tables, *backup_handler_tables; + TABLE *backup_open_tables; DBUG_ENTER("mysql_ha_open"); DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d", tables->db, tables->table_name, tables->alias, @@ -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; - backup_handler_tables= thd->handler_tables; + /* + Save and reset the open_tables list so that open_tables() won't + 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; - /* to avoid flushes */ - thd->handler_tables= NULL; /* open_tables() will set 'tables->table' if successful. @@ -231,9 +237,12 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) error= open_tables(thd, &tables, &counter, 0); /* restore the state and merge the opened table into handler_tables list */ - thd->handler_tables= thd->open_tables ? - thd->open_tables->next= backup_handler_tables, - thd->open_tables : backup_handler_tables; + if (thd->open_tables) + { + thd->open_tables->next= thd->handler_tables; + thd->handler_tables= thd->open_tables; + } + thd->open_tables= backup_open_tables; if (error) @@ -360,7 +369,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ha_rows select_limit_cnt, ha_rows offset_limit_cnt) { TABLE_LIST *hash_tables; - TABLE *table, *backup_open_tables, *backup_handler_tables; + TABLE *table, *backup_open_tables; MYSQL_LOCK *lock; List<Item> list; Protocol *protocol= thd->protocol; @@ -437,20 +446,20 @@ retry: } tables->table=table; - /* save open_ and handler_ tables state */ + /* save open_tables state */ backup_open_tables= thd->open_tables; - backup_handler_tables= thd->handler_tables; - - /* no pre-opened tables */ - thd->open_tables= NULL; - /* to avoid flushes */ - thd->handler_tables= NULL; + /* + mysql_lock_tables() needs thd->open_tables to be set correctly to + be able to handle aborts properly. When the abort happens, it's + safe to not protect thd->handler_tables because it won't close any + tables. + */ + thd->open_tables= thd->handler_tables; lock= mysql_lock_tables(thd, &tables->table, 1, MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen); /* restore previous context */ - thd->handler_tables= backup_handler_tables; thd->open_tables= backup_open_tables; if (need_reopen) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 553cc6d24d5..9c07add98d4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1570,13 +1570,15 @@ sp_name: | ident { LEX *lex= Lex; - LEX_STRING db; + LEX_STRING db= {0,0}; + THD *thd= YYTHD; + if (check_routine_name($1)) { my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); MYSQL_YYABORT; } - if (lex->copy_db_to(&db.str, &db.length)) + if (thd->db && thd->copy_db_to(&db.str, &db.length)) MYSQL_YYABORT; $$= new sp_name(db, $1, false); if ($$) @@ -1626,6 +1628,13 @@ create_function_tail: my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"); 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 */ sp= new sp_head(); sp->reset_thd_mem_root(thd); @@ -5195,8 +5204,8 @@ simple_expr: #endif /* HAVE_DLOPEN */ { THD *thd= lex->thd; - LEX_STRING db; - if (lex->copy_db_to(&db.str, &db.length)) + LEX_STRING db= {0,0}; + if (thd->db && thd->copy_db_to(&db.str, &db.length)) MYSQL_YYABORT; sp_name *name= new sp_name(db, $1, false); if (name) @@ -9745,7 +9754,13 @@ trigger_tail: my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); 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())) MYSQL_YYABORT; sp->reset_thd_mem_root(thd); @@ -9828,6 +9843,12 @@ sp_tail: 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; /* Order is important here: new - reset - init */ |