summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2005-12-06 18:38:03 +0100
committerunknown <ingo@mysql.com>2005-12-06 18:38:03 +0100
commit45a4fbb2e68323375423f4290e08c03e8ae4038b (patch)
tree6187dd20934c97ef66392158802003ff86b87f45 /sql
parentf77305608ee22e31cf79cce780ffc0256c32e2b6 (diff)
parent29eac312cda3bebddeb7f5ab7a2af6b81ea89205 (diff)
downloadmariadb-git-45a4fbb2e68323375423f4290e08c03e8ae4038b.tar.gz
Merge mysql.com:/home/mydev/mysql-5.0
into mysql.com:/home/mydev/mysql-5.0-bug10932
Diffstat (limited to 'sql')
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp.cc105
-rw-r--r--sql/sp.h10
-rw-r--r--sql/sql_base.cc47
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_trigger.h2
-rw-r--r--sql/sql_yacc.yy5
7 files changed, 133 insertions, 46 deletions
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index f67ad3a9fd2..d7a534fb7b9 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5600,3 +5600,5 @@ ER_OLD_FILE_FORMAT
eng "'%-.64s' has an old format, you should re-create the '%s' object(s)"
ER_SP_RECURSION_LIMIT
eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.64s"
+ER_SP_PROC_TABLE_CORRUPT
+ eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
diff --git a/sql/sp.cc b/sql/sp.cc
index 8991cc78b5e..3e5a3cb94f1 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1446,21 +1446,23 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src)
first_no_prelock - If true, don't add tables or cache routines used by
the body of the first routine (i.e. *start)
will be executed in non-prelocked mode.
+ tabs_changed - Set to TRUE some tables were added, FALSE otherwise
NOTE
If some function is missing this won't be reported here.
Instead this fact will be discovered during query execution.
RETURN VALUE
- TRUE - some tables were added
- FALSE - no tables were added.
+ 0 - success
+ non-0 - failure
*/
-static bool
+static int
sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
Sroutine_hash_entry *start,
- bool first_no_prelock)
+ bool first_no_prelock, bool *tabs_changed)
{
- bool result= FALSE;
+ int ret= 0;
+ bool tabschnd= 0; /* Set if tables changed */
bool first= TRUE;
DBUG_ENTER("sp_cache_routines_and_add_tables_aux");
@@ -1481,12 +1483,50 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
name.m_name.str+= 1;
name.m_name.length= name.m_qname.length - name.m_db.length - 1;
- if (db_find_routine(thd, type, &name, &sp) == SP_OK)
+ switch ((ret= db_find_routine(thd, type, &name, &sp)))
{
- if (type == TYPE_ENUM_FUNCTION)
- sp_cache_insert(&thd->sp_func_cache, sp);
- else
- sp_cache_insert(&thd->sp_proc_cache, sp);
+ case SP_OK:
+ {
+ if (type == TYPE_ENUM_FUNCTION)
+ sp_cache_insert(&thd->sp_func_cache, sp);
+ else
+ sp_cache_insert(&thd->sp_proc_cache, sp);
+ }
+ break;
+ case SP_KEY_NOT_FOUND:
+ ret= SP_OK;
+ break;
+ case SP_OPEN_TABLE_FAILED:
+ /*
+ Force it to attempt opening it again on subsequent calls;
+ otherwise we will get one error message the first time, and
+ then ER_SP_PROC_TABLE_CORRUPT (below) on subsequent tries.
+ */
+ mysql_proc_table_exists= 1;
+ /* Fall through */
+ default:
+ /*
+ Any error when loading an existing routine is either some problem
+ with the mysql.proc table, or a parse error because the contents
+ has been tampered with (in which case we clear that error).
+ */
+ if (ret == SP_PARSE_ERROR)
+ thd->clear_error();
+ /*
+ If we cleared the parse error, or when db_find_routine() flagged
+ an error with it's return value without calling my_error(), we
+ set the generic "mysql.proc table corrupt" error here.
+ */
+ if (!thd->net.report_error)
+ {
+ char n[NAME_LEN*2+2];
+
+ /* m_qname.str is not always \0 terminated */
+ memcpy(n, name.m_qname.str, name.m_qname.length);
+ n[name.m_qname.length]= '\0';
+ my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret);
+ }
+ break;
}
}
if (sp)
@@ -1494,12 +1534,15 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
if (!(first && first_no_prelock))
{
sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines);
- result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last);
+ tabschnd|=
+ sp->add_used_tables_to_table_list(thd, &lex->query_tables_last);
}
}
first= FALSE;
}
- DBUG_RETURN(result);
+ if (tabs_changed) /* it can be NULL */
+ *tabs_changed= tabschnd;
+ DBUG_RETURN(ret);
}
@@ -1514,18 +1557,20 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
lex - LEX representing statement
first_no_prelock - If true, don't add tables or cache routines used by
the body of the first routine (i.e. *start)
+ tabs_changed - Set to TRUE some tables were added, FALSE otherwise
RETURN VALUE
- TRUE - some tables were added
- FALSE - no tables were added.
+ 0 - success
+ non-0 - failure
*/
-bool
-sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock)
+int
+sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock,
+ bool *tabs_changed)
{
return sp_cache_routines_and_add_tables_aux(thd, lex,
(Sroutine_hash_entry *)lex->sroutines_list.first,
- first_no_prelock);
+ first_no_prelock, tabs_changed);
}
@@ -1539,16 +1584,21 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock)
thd - thread context
lex - LEX representing statement
aux_lex - LEX representing view
+
+ RETURN VALUE
+ 0 - success
+ non-0 - failure
*/
-void
+int
sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
{
Sroutine_hash_entry **last_cached_routine_ptr=
(Sroutine_hash_entry **)lex->sroutines_list.next;
sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list);
- (void)sp_cache_routines_and_add_tables_aux(thd, lex,
- *last_cached_routine_ptr, FALSE);
+ return sp_cache_routines_and_add_tables_aux(thd, lex,
+ *last_cached_routine_ptr, FALSE,
+ NULL);
}
@@ -1562,12 +1612,18 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
thd - thread context
lex - LEX respresenting statement
triggers - triggers of the table
+
+ RETURN VALUE
+ 0 - success
+ non-0 - failure
*/
-void
+int
sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers)
{
+ int ret= 0;
+
if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key))
{
Sroutine_hash_entry **last_cached_routine_ptr=
@@ -1585,10 +1641,11 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
}
}
}
- (void)sp_cache_routines_and_add_tables_aux(thd, lex,
- *last_cached_routine_ptr,
- FALSE);
+ ret= sp_cache_routines_and_add_tables_aux(thd, lex,
+ *last_cached_routine_ptr,
+ FALSE, NULL);
}
+ return ret;
}
diff --git a/sql/sp.h b/sql/sp.h
index 7f314b8903e..235eb5cba37 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -84,11 +84,11 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena,
sp_name *rt, char rt_type);
void sp_remove_not_own_routines(LEX *lex);
void sp_update_sp_used_routines(HASH *dst, HASH *src);
-bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
- bool first_no_prelock);
-void sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
- LEX *aux_lex);
-void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
+int sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
+ bool first_no_prelock, bool *tabs_changed);
+int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
+ LEX *aux_lex);
+int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers);
extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 39e15675e47..35f4bd9a05f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1984,15 +1984,25 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
if (!thd->prelocked_mode && !thd->lex->requires_prelocking() &&
thd->lex->sroutines_list.elements)
{
- bool first_no_prelocking, need_prelocking;
+ bool first_no_prelocking, need_prelocking, tabs_changed;
TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
DBUG_ASSERT(thd->lex->query_tables == *start);
sp_get_prelocking_info(thd, &need_prelocking, &first_no_prelocking);
- if ((sp_cache_routines_and_add_tables(thd, thd->lex,
- first_no_prelocking) ||
- *start) && need_prelocking)
+ if (sp_cache_routines_and_add_tables(thd, thd->lex,
+ first_no_prelocking,
+ &tabs_changed))
+ {
+ /*
+ Serious error during reading stored routines from mysql.proc table.
+ Something's wrong with the table or its contents, and an error has
+ been emitted; we must abort.
+ */
+ result= -1;
+ goto err;
+ }
+ else if ((tabs_changed || *start) && need_prelocking)
{
query_tables_last_own= save_query_tables_last;
*start= thd->lex->query_tables;
@@ -2116,9 +2126,18 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
tables->lock_type >= TL_WRITE_ALLOW_WRITE)
{
if (!query_tables_last_own)
- query_tables_last_own= thd->lex->query_tables_last;
- sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex,
- tables->table->triggers);
+ query_tables_last_own= thd->lex->query_tables_last;
+ if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex,
+ tables->table->triggers))
+ {
+ /*
+ Serious error during reading stored routines from mysql.proc table.
+ Something's wrong with the table or its contents, and an error has
+ been emitted; we must abort.
+ */
+ result= -1;
+ goto err;
+ }
}
free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC));
}
@@ -2139,9 +2158,21 @@ process_view_routines:
/* We have at least one table in TL here. */
if (!query_tables_last_own)
query_tables_last_own= thd->lex->query_tables_last;
- sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables->view);
+ if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex,
+ tables->view))
+ {
+ /*
+ Serious error during reading stored routines from mysql.proc table.
+ Something's wrong with the table or its contents, and an error has
+ been emitted; we must abort.
+ */
+ result= -1;
+ goto err;
+ }
}
}
+
+ err:
thd->proc_info=0;
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 94ce66bd71d..7430cbffeeb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4133,14 +4133,6 @@ end_with_restore_list:
}
}
#endif
- if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
- !(lex->sphead->m_flags & sp_head::HAS_RETURN))
- {
- my_error(ER_SP_NORETURN, MYF(0), name);
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
/*
We need to copy name and db in order to use them for
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 6be42d7b868..143f9f4d5bd 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -117,7 +117,7 @@ public:
void set_table(TABLE *new_table);
friend class Item_trigger_field;
- friend void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
+ friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers);
private:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c20b1792718..fbcb3de7907 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1407,6 +1407,11 @@ create_function_tail:
YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex, lex->spname);
+ if (!(sp->m_flags & sp_head::HAS_RETURN))
+ {
+ my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
+ YYABORT;
+ }
/* Restore flag if it was cleared above */
if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;