summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2005-08-23 23:17:36 +0300
committerunknown <bell@sanja.is.com.ua>2005-08-23 23:17:36 +0300
commiteb7c4ff2dbcfcc0292dcd1ff577b1d203463834c (patch)
treeb23f9eadbed55b7a8cbac4da9ef2cc8338d7fa44 /sql
parent142f65834b73e99cce98d9c537c22584bdd81033 (diff)
parent705118d1f627c6aa9a14f2a00f080b13af7b3484 (diff)
downloadmariadb-git-eb7c4ff2dbcfcc0292dcd1ff577b1d203463834c.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-bug3-5.0 BitKeeper/etc/config: Auto merged sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_delete.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_view.cc: Auto merged sql/table.cc: Auto merged mysql-test/r/view.result: merge mysql-test/t/view.test: merge sql/share/errmsg.txt: merge sql/sql_insert.cc: merge sql/table.h: merge
Diffstat (limited to 'sql')
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_base.cc58
-rw-r--r--sql/sql_delete.cc21
-rw-r--r--sql/sql_insert.cc5
-rw-r--r--sql/sql_parse.cc18
-rw-r--r--sql/sql_update.cc23
-rw-r--r--sql/sql_view.cc7
-rw-r--r--sql/table.cc2
-rw-r--r--sql/table.h2
10 files changed, 108 insertions, 33 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 085bb0166cc..8807ae3c89d 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -895,6 +895,9 @@ void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item);
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
+void update_non_unique_table_error(TABLE_LIST *update,
+ const char *operation,
+ TABLE_LIST *duplicate);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds,
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index b49b7248021..81e953e3a5d 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5399,3 +5399,5 @@ ER_DATETIME_FUNCTION_OVERFLOW 22008
eng "Datetime function: %-.32s field overflow"
ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
+ER_VIEW_PREVENT_UPDATE
+ eng "The definition of table '%-.64s' prevents operation %s on table '%-.64s'."
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 763fbc6c336..3de54f92590 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -774,6 +774,60 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
}
+/*
+ Issue correct error message in case we found 2 duplicate tables which
+ prevent some update operation
+
+ SYNOPSIS
+ update_non_unique_table_error()
+ update table which we try to update
+ operation name of update operation
+ duplicate duplicate table which we found
+
+ NOTE:
+ here we hide view underlying tables if we have them
+*/
+
+void update_non_unique_table_error(TABLE_LIST *update,
+ const char *operation,
+ TABLE_LIST *duplicate)
+{
+ update= update->top_table();
+ duplicate= duplicate->top_table();
+ if (!update->view || !duplicate->view ||
+ update->view == duplicate->view ||
+ update->view_name.length != duplicate->view_name.length ||
+ update->view_db.length != duplicate->view_db.length ||
+ my_strcasecmp(table_alias_charset,
+ update->view_name.str, duplicate->view_name.str) != 0 ||
+ my_strcasecmp(table_alias_charset,
+ update->view_db.str, duplicate->view_db.str) != 0)
+ {
+ /*
+ it is not the same view repeated (but it can be parts of the same copy
+ of view), so we have to hide underlying tables.
+ */
+ if (update->view)
+ {
+ if (update->view == duplicate->view)
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation);
+ else
+ my_error(ER_VIEW_PREVENT_UPDATE, MYF(0),
+ (duplicate->view ? duplicate->alias : update->alias),
+ operation, update->alias);
+ return;
+ }
+ if (duplicate->view)
+ {
+ my_error(ER_VIEW_PREVENT_UPDATE, MYF(0), duplicate->alias, operation,
+ update->alias);
+ return;
+ }
+ }
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), update->alias);
+}
+
+
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
{
char key[MAX_DBKEY_LENGTH];
@@ -4153,9 +4207,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
{
TABLE *table= table_list->table;
if (first_select_table &&
- (table_list->belong_to_view ?
- table_list->belong_to_view :
- table_list) == first_select_table)
+ table_list->top_table() == first_select_table)
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 35183fc959b..70325f2a411 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -312,10 +312,13 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(TRUE);
}
- if (unique_table(table_list, table_list->next_global))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
- DBUG_RETURN(TRUE);
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
+ {
+ update_non_unique_table_error(table_list, "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
}
select_lex->fix_prepare_information(thd, conds);
DBUG_RETURN(FALSE);
@@ -398,11 +401,15 @@ bool mysql_multi_delete_prepare(THD *thd)
Check that table from which we delete is not used somewhere
inside subqueries/view.
*/
- if (unique_table(target_tbl->correspondent_table, lex->query_tables))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0),
- target_tbl->correspondent_table->table_name);
- DBUG_RETURN(TRUE);
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(target_tbl->correspondent_table,
+ lex->query_tables)))
+ {
+ update_non_unique_table_error(target_tbl->correspondent_table,
+ "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
}
}
DBUG_RETURN(FALSE);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 93c9991418d..43a23dd31f0 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -917,9 +917,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (!select_insert)
{
Item *fake_conds= 0;
- if (unique_table(table_list, table_list->next_global))
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
+ update_non_unique_table_error(table_list, "INSERT", duplicate);
DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, &fake_conds);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 31d0f3eb675..18f8de4e86e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2854,12 +2854,15 @@ mysql_execute_command(THD *thd)
Is table which we are changing used somewhere in other parts
of query
*/
- if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- unique_table(create_table, select_tables))
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->table_name);
- res= 1;
- goto end_with_restart_wait;
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(create_table, select_tables)))
+ {
+ update_non_unique_table_error(create_table, "CREATE", duplicate);
+ res= 1;
+ goto end_with_restart_wait;
+ }
}
/* If we create merge table, we have to test tables in merge, too */
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
@@ -2869,9 +2872,10 @@ mysql_execute_command(THD *thd)
tab;
tab= tab->next_local)
{
- if (unique_table(tab, select_tables))
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(tab, select_tables)))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), tab->table_name);
+ update_non_unique_table_error(tab, "CREATE", duplicate);
res= 1;
goto end_with_restart_wait;
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b596420692a..42c06d478be 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -566,10 +566,14 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
/* Check that we are not using table that we are updating in a sub select */
- if (unique_table(table_list, table_list->next_global))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
- DBUG_RETURN(TRUE);
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
+ {
+ update_non_unique_table_error(table_list, "UPDATE", duplicate);
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
+ DBUG_RETURN(TRUE);
+ }
}
select_lex->fix_prepare_information(thd, conds);
DBUG_RETURN(FALSE);
@@ -779,7 +783,7 @@ bool mysql_multi_update_prepare(THD *thd)
{
TABLE *table= tl->table;
TABLE_LIST *tlist;
- if (!(tlist= tl->belong_to_view ? tl->belong_to_view : tl)->derived)
+ if (!(tlist= tl->top_table())->derived)
{
tlist->grant.want_privilege=
(SELECT_ACL & ~tlist->grant.privilege);
@@ -788,11 +792,14 @@ bool mysql_multi_update_prepare(THD *thd)
DBUG_PRINT("info", ("table: %s want_privilege: %u", tl->alias,
(uint) table->grant.want_privilege));
if (tl->lock_type != TL_READ &&
- tl->lock_type != TL_READ_NO_INSERT &&
- unique_table(tl, table_list))
+ tl->lock_type != TL_READ_NO_INSERT)
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
- DBUG_RETURN(TRUE);
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(tl, table_list)))
+ {
+ update_non_unique_table_error(table_list, "UPDATE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
}
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index dcada0c0780..82e4d6e136a 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -763,9 +763,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
if (!res && !thd->is_fatal_error)
{
- TABLE_LIST *top_view= (table->belong_to_view ?
- table->belong_to_view :
- table);
+ TABLE_LIST *top_view= table->top_table();
TABLE_LIST *view_tables= lex->query_tables;
TABLE_LIST *view_tables_tail= 0;
TABLE_LIST *tbl;
@@ -1134,8 +1132,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
thd->lex->select_lex.select_limit == 0)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table;
- if (view->belong_to_view)
- view= view->belong_to_view;
+ view= view->top_table();
trans= view->field_translation;
key_info_end= (key_info= table->key_info)+ table->s->keys;
diff --git a/sql/table.cc b/sql/table.cc
index 66fccec9c24..40f30dc15d8 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2056,7 +2056,7 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
{
if (check_option && check_option->val_int() == 0)
{
- TABLE_LIST *view= (belong_to_view ? belong_to_view : this);
+ TABLE_LIST *view= top_table();
if (ignore_failure)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
diff --git a/sql/table.h b/sql/table.h
index c9095ad48f6..d7c14e1938a 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -602,6 +602,8 @@ typedef struct st_table_list
st_table_list *first_leaf_for_name_resolution();
st_table_list *last_leaf_for_name_resolution();
bool is_leaf_for_name_resolution();
+ inline st_table_list *top_table()
+ { return belong_to_view ? belong_to_view : this; }
inline bool prepare_check_option(THD *thd)
{
bool res= FALSE;