summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc577
1 files changed, 319 insertions, 258 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 34a668472e2..fe2d6f8faa1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -540,6 +540,8 @@ void init_update_queries(void)
uc_update_queries[SQLCOM_DELETE_MULTI]=1;
uc_update_queries[SQLCOM_DROP_INDEX]=1;
uc_update_queries[SQLCOM_UPDATE_MULTI]=1;
+ uc_update_queries[SQLCOM_CREATE_VIEW]=1;
+ uc_update_queries[SQLCOM_DROP_VIEW]=1;
}
bool is_update_query(enum enum_sql_command command)
@@ -1181,10 +1183,10 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
db = (db && db[0]) ? db : thd->db;
if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory
- table_list->db = db;
- table_list->real_name = table_list->alias = tbl_name;
- table_list->lock_type = TL_READ_NO_INSERT;
- table_list->next = 0;
+ table_list->db= db;
+ table_list->real_name= table_list->alias= tbl_name;
+ table_list->lock_type= TL_READ_NO_INSERT;
+ table_list->prev_global= &table_list; // can be removed after merge with 4.1
if (!db || check_db_name(db))
{
@@ -1877,11 +1879,35 @@ mysql_execute_command(THD *thd)
{
int res= 0;
LEX *lex= thd->lex;
- TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
+ /* first table of first SELECT_LEX */
+ TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
+ /* list of all tables in query */
+ TABLE_LIST *all_tables;
+ /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= &lex->select_lex;
+ /* most outer SELECT_LEX_UNIT of query */
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
+ /*
+ In many cases first table of main SELECT_LEX have special meaning =>
+ check that it is first table in global list and relink it first in
+ queries_tables list if it is necessary (we need such relinking only
+ for queries with subqueries in select list, in this case tables of
+ subqueries will go to global list first)
+
+ all_tables will differ from first_table only if most upper SELECT_LEX
+ do not contain tables.
+
+ Because of above in place where should be at least one table in most
+ outer SELECT_LEX we have following check:
+ DBUG_ASSERT(first_table == all_tables);
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ */
+ lex->first_lists_tables_same();
+ /* should be assigned after making firts tables same */
+ all_tables= lex->query_tables;
+
if (lex->sql_command != SQLCOM_CREATE_PROCEDURE &&
lex->sql_command != SQLCOM_CREATE_SPFUNCTION)
{
@@ -1895,7 +1921,7 @@ mysql_execute_command(THD *thd)
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
*/
- if (tables || &lex->select_lex != lex->all_selects_list)
+ if (all_tables || &lex->select_lex != lex->all_selects_list)
mysql_reset_errors(thd);
#ifdef HAVE_REPLICATION
@@ -1905,7 +1931,7 @@ mysql_execute_command(THD *thd)
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated
*/
- if (all_tables_not_ok(thd,tables))
+ if (all_tables_not_ok(thd, all_tables))
{
/* we warn the slave SQL thread */
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
@@ -1925,9 +1951,6 @@ mysql_execute_command(THD *thd)
#endif
}
#endif /* !HAVE_REPLICATION */
- if (&lex->select_lex != lex->all_selects_list &&
- lex->unit.create_total_list(thd, lex, &tables))
- DBUG_RETURN(0);
/*
When option readonly is set deny operations which change tables.
@@ -1953,23 +1976,24 @@ mysql_execute_command(THD *thd)
}
select_result *result=lex->result;
- if (tables)
+ if (all_tables)
{
- res=check_table_access(thd,
- lex->exchange ? SELECT_ACL | FILE_ACL :
- SELECT_ACL,
- tables,0);
+ res= check_table_access(thd,
+ lex->exchange ? SELECT_ACL | FILE_ACL :
+ SELECT_ACL,
+ all_tables, 0);
}
else
- res=check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
- any_db,0,0,0);
+ res= check_access(thd,
+ lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
+ any_db, 0, 0, 0);
if (res)
{
res=0;
break; // Error message is given
}
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
{
@@ -2006,7 +2030,7 @@ mysql_execute_command(THD *thd)
break;
}
}
- query_cache_store_query(thd, tables);
+ query_cache_store_query(thd, all_tables);
res=handle_select(thd, lex, result);
}
}
@@ -2105,8 +2129,9 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_DO:
- if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
- (res= open_and_lock_tables(thd,tables))))
+ if (all_tables &&
+ ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
+ (res= open_and_lock_tables(thd, all_tables))))
break;
res= mysql_do(thd, *lex->insert_list);
@@ -2188,41 +2213,45 @@ mysql_execute_command(THD *thd)
case SQLCOM_BACKUP_TABLE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL, tables,0) ||
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- res = mysql_backup_table(thd, tables);
+ res = mysql_backup_table(thd, first_table);
break;
}
case SQLCOM_RESTORE_TABLE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, INSERT_ACL, tables,0) ||
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, INSERT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- res = mysql_restore_table(thd, tables);
+ res = mysql_restore_table(thd, first_table);
break;
}
case SQLCOM_ASSIGN_TO_KEYCACHE:
{
- if (check_db_used(thd, tables) ||
- check_access(thd, INDEX_ACL, tables->db,
- &tables->grant.privilege, 0, 0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, INDEX_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0))
goto error;
- res= mysql_assign_to_keycache(thd, tables, &lex->name_and_length);
+ res= mysql_assign_to_keycache(thd, first_table, &lex->name_and_length);
break;
}
case SQLCOM_PRELOAD_KEYS:
{
- if (check_db_used(thd, tables) ||
- check_access(thd, INDEX_ACL, tables->db,
- &tables->grant.privilege, 0, 0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, INDEX_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0))
goto error;
- res = mysql_preload_keys(thd, tables);
+ res = mysql_preload_keys(thd, first_table);
break;
}
#ifdef HAVE_REPLICATION
@@ -2275,19 +2304,21 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
case SQLCOM_LOAD_MASTER_TABLE:
{
- if (!tables->db)
- tables->db=thd->db;
- if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (!first_table->db)
+ first_table->db= thd->db;
+ if (check_access(thd, CREATE_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
if (grant_option)
{
/* Check that the first table has CREATE privilege */
- if (check_grant(thd, CREATE_ACL, tables, 0, 1, 0))
+ if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
goto error;
}
- if (strlen(tables->real_name) > NAME_LEN)
+ if (strlen(first_table->real_name) > NAME_LEN)
{
- net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name);
+ net_printf(thd, ER_WRONG_TABLE_NAME, first_table->real_name);
break;
}
pthread_mutex_lock(&LOCK_active_mi);
@@ -2295,7 +2326,7 @@ mysql_execute_command(THD *thd)
fetch_master_table will send the error to the client on failure.
Give error if the table already exists.
*/
- if (!fetch_master_table(thd, tables->db, tables->real_name,
+ if (!fetch_master_table(thd, first_table->db, first_table->real_name,
active_mi, 0, 0))
{
send_ok(thd);
@@ -2307,12 +2338,13 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_TABLE:
{
- /* Skip first table, which is the table we are creating */
- TABLE_LIST *create_table, *create_table_local;
- tables= lex->unlink_first_table(tables, &create_table,
- &create_table_local);
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ bool link_to_local;
+ // Skip first table, which is the table we are creating
+ TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
+ TABLE_LIST *select_tables= lex->query_tables;
- if ((res= create_table_precheck(thd, tables, create_table)))
+ if ((res= create_table_precheck(thd, select_tables, create_table)))
goto unsent_create_error;
#ifndef HAVE_READLINK
@@ -2321,7 +2353,7 @@ mysql_execute_command(THD *thd)
/* Fix names if symlinked tables */
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
create_table->real_name) ||
- append_file_to_dir(thd,&lex->create_info.index_file_name,
+ append_file_to_dir(thd, &lex->create_info.index_file_name,
create_table->real_name))
{
res=-1;
@@ -2344,28 +2376,32 @@ mysql_execute_command(THD *thd)
if (select_lex->item_list.elements) // With select
{
select_result *result;
-
+ /*
+ Is table which we are changing used somewhere in other parts
+ of query
+ */
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- find_real_table_in_list(tables, create_table->db,
+ find_real_table_in_list(select_tables, create_table->db,
create_table->real_name))
{
- net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
+ net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name);
goto create_error;
}
- if (tables && check_table_access(thd, SELECT_ACL, tables,0))
+ if (select_tables &&
+ check_table_access(thd, SELECT_ACL, select_tables, 0))
goto create_error; // Error message is given
select_lex->options|= SELECT_NO_UNLOCK;
unit->set_limit(select_lex, select_lex);
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(res= open_and_lock_tables(thd, select_tables)))
{
res= -1; // If error
- if ((result=new select_create(create_table->db,
- create_table->real_name,
- &lex->create_info,
- lex->create_list,
- lex->key_list,
- select_lex->item_list,lex->duplicates)))
+ if ((result= new select_create(create_table,
+ &lex->create_info,
+ lex->create_list,
+ lex->key_list,
+ select_lex->item_list,
+ lex->duplicates)))
{
/*
CREATE from SELECT give its SELECT_LEX for SELECT,
@@ -2388,36 +2424,33 @@ mysql_execute_command(THD *thd)
(Table_ident *)lex->name);
else
{
- res= mysql_create_table(thd,create_table->db,
- create_table->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,0,0,0); // do logging
+ res= mysql_create_table(thd, create_table->db,
+ create_table->real_name, &lex->create_info,
+ lex->create_list,
+ lex->key_list, 0, 0, 0); // do logging
}
if (!res)
send_ok(thd);
}
-
- /* put tables back for PS rexecuting */
- tables= lex->link_first_table_back(tables, create_table,
- create_table_local);
+ lex->link_first_table_back(create_table, link_to_local);
break;
create_error:
- res= 1; //error reported
+ res= 1; //error reported
unsent_create_error:
/* put tables back for PS rexecuting */
- tables= lex->link_first_table_back(tables, create_table,
- create_table_local);
+ lex->link_first_table_back(create_table, link_to_local);
break;
}
case SQLCOM_CREATE_INDEX:
- if (check_one_table_access(thd, INDEX_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
if (end_active_trans(thd))
res= -1;
else
- res = mysql_create_index(thd, tables, lex->key_list);
+ res = mysql_create_index(thd, first_table, lex->key_list);
break;
#ifdef HAVE_REPLICATION
@@ -2456,6 +2489,7 @@ unsent_create_error:
#endif /* HAVE_REPLICATION */
case SQLCOM_ALTER_TABLE:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
goto error;
@@ -2469,16 +2503,17 @@ unsent_create_error:
break;
}
if (!select_lex->db)
- select_lex->db=tables->db;
- if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege,0,0) ||
+ select_lex->db= first_table->db;
+ if (check_access(thd, ALTER_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0) ||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
- check_merge_table_access(thd, tables->db,
+ check_merge_table_access(thd, first_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
if (grant_option)
{
- if (check_grant(thd, ALTER_ACL, tables, 0, UINT_MAX, 0))
+ if (check_grant(thd, ALTER_ACL, all_tables, 0, UINT_MAX, 0))
goto error;
if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
@@ -2502,7 +2537,7 @@ unsent_create_error:
thd->slow_command=TRUE;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
- tables, lex->create_list,
+ first_table, lex->create_list,
lex->key_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
@@ -2513,38 +2548,37 @@ unsent_create_error:
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
case SQLCOM_RENAME_TABLE:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *table;
- if (check_db_used(thd,tables))
+ if (check_db_used(thd, all_tables))
goto error;
- for (table=tables ; table ; table=table->next->next)
+ for (table= first_table; table; table= table->next_local->next_local)
{
if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
&table->grant.privilege,0,0) ||
- check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db,
- &table->next->grant.privilege,0,0))
+ check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
+ &table->next_local->grant.privilege, 0, 0))
goto error;
if (grant_option)
{
- TABLE_LIST old_list,new_list;
+ TABLE_LIST old_list, new_list;
/*
we do not need initialize old_list and new_list because we will
come table[0] and table->next[0] there
*/
- old_list=table[0];
- new_list=table->next[0];
- old_list.next=new_list.next=0;
- if (check_grant(thd, ALTER_ACL, &old_list, 0, UINT_MAX, 0) ||
- (!test_all_bits(table->next->grant.privilege,
+ old_list= table[0];
+ new_list= table->next_local[0];
+ if (check_grant(thd, ALTER_ACL, &old_list, 0, 1, 0) ||
+ (!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
- check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0,
- UINT_MAX, 0)))
+ check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
goto error;
}
}
- query_cache_invalidate3(thd, tables, 0);
+ query_cache_invalidate3(thd, first_table, 0);
if (end_active_trans(thd))
res= -1;
- else if (mysql_rename_tables(thd,tables))
+ else if (mysql_rename_tables(thd, first_table))
res= -1;
break;
}
@@ -2563,34 +2597,37 @@ unsent_create_error:
#endif
#endif /* EMBEDDED_LIBRARY */
case SQLCOM_SHOW_CREATE:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
goto error;
#else
{
- if (check_db_used(thd, tables) ||
- check_access(thd, SELECT_ACL | EXTRA_ACL, tables->db,
- &tables->grant.privilege,0,0))
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0))
goto error;
- res = mysqld_show_create(thd, tables);
+ res = mysqld_show_create(thd, first_table);
break;
}
#endif
case SQLCOM_CHECKSUM:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0))
goto error; /* purecov: inspected */
- res = mysql_checksum_table(thd, tables, &lex->check_opt);
+ res = mysql_checksum_table(thd, first_table, &lex->check_opt);
break;
}
case SQLCOM_REPAIR:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- res = mysql_repair_table(thd, tables, &lex->check_opt);
+ res= mysql_repair_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
@@ -2604,20 +2641,22 @@ unsent_create_error:
}
case SQLCOM_CHECK:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- res = mysql_check_table(thd, tables, &lex->check_opt);
+ res = mysql_check_table(thd, first_table, &lex->check_opt);
break;
}
case SQLCOM_ANALYZE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- res = mysql_analyze_table(thd, tables, &lex->check_opt);
+ res = mysql_analyze_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
@@ -2632,13 +2671,14 @@ unsent_create_error:
case SQLCOM_OPTIMIZE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
- mysql_recreate_table(thd, tables, 1) :
- mysql_optimize_table(thd, tables, &lex->check_opt);
+ mysql_recreate_table(thd, first_table, 1) :
+ mysql_optimize_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
@@ -2651,9 +2691,10 @@ unsent_create_error:
break;
}
case SQLCOM_UPDATE:
- if (update_precheck(thd, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (update_precheck(thd, all_tables))
break;
- res= mysql_update(thd,tables,
+ res= mysql_update(thd, all_tables,
select_lex->item_list,
lex->value_list,
select_lex->where,
@@ -2666,9 +2707,10 @@ unsent_create_error:
break;
case SQLCOM_UPDATE_MULTI:
{
- if ((res= multi_update_precheck(thd, tables)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= multi_update_precheck(thd, all_tables)))
break;
- res= mysql_multi_update(thd,tables,
+ res= mysql_multi_update(thd, all_tables,
&select_lex->item_list,
&lex->value_list,
select_lex->where,
@@ -2679,26 +2721,29 @@ unsent_create_error:
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
- my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
- if ((res= insert_precheck(thd, tables, update)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
+ if ((res= insert_precheck(thd, all_tables, update)))
break;
- res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- select_lex->item_list, lex->value_list,
- (update ? DUP_UPDATE : lex->duplicates));
+ res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
+ select_lex->item_list, lex->value_list,
+ (update ? DUP_UPDATE : lex->duplicates));
if (thd->net.report_error)
res= -1;
+ if (first_table->view && !first_table->contain_auto_increment)
+ thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
break;
}
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
- TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first;
- if ((res= insert_select_precheck(thd, tables)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= insert_select_precheck(thd, all_tables)))
break;
/* Fix lock for first table */
- if (tables->lock_type == TL_WRITE_DELAYED)
- tables->lock_type= TL_WRITE;
+ if (first_table->lock_type == TL_WRITE_DELAYED)
+ first_table->lock_type= TL_WRITE;
/* Don't unlock tables until command is written to binary log */
select_lex->options|= SELECT_NO_UNLOCK;
@@ -2706,37 +2751,45 @@ unsent_create_error:
select_result *result;
unit->set_limit(select_lex, select_lex);
- if (find_real_table_in_list(tables->next, tables->db, tables->real_name))
+ // is table which we are changing used somewhere in other parts of query
+ if (find_real_table_in_list(all_tables->next_global,
+ first_table->db, first_table->real_name))
{
/* Using same table for INSERT and SELECT */
select_lex->options |= OPTION_BUFFER_RESULT;
}
-
- if (!(res=open_and_lock_tables(thd, tables)))
+ if (!(res= open_and_lock_tables(thd, all_tables)))
{
- if ((result=new select_insert(tables->table,&lex->field_list,
- lex->duplicates)))
+ if ((res= mysql_insert_select_prepare(thd)))
+ break;
+ if ((result= new select_insert(first_table, first_table->table,
+ &lex->field_list, lex->duplicates)))
/* Skip first table, which is the table we are inserting in */
- lex->select_lex.table_list.first= (byte*) first_local_table->next;
+ lex->select_lex.table_list.first= (byte*) first_table->next_local;
/*
insert/replace from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
- res=handle_select(thd,lex,result);
+ res= handle_select(thd, lex, result);
/* revert changes for SP */
- lex->select_lex.table_list.first= (byte*) first_local_table;
+ lex->select_lex.table_list.first= (byte*) first_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
if (thd->net.report_error)
res= -1;
}
else
res= -1;
+
+ if (first_table->view && !first_table->contain_auto_increment)
+ thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
+
break;
}
case SQLCOM_TRUNCATE:
- if (check_one_table_access(thd, DELETE_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, DELETE_ACL, all_tables))
goto error;
/*
Don't allow this within a transaction because we want to use
@@ -2747,13 +2800,15 @@ unsent_create_error:
send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
goto error;
}
- res=mysql_truncate(thd,tables);
+
+ res= mysql_truncate(thd, first_table);
break;
case SQLCOM_DELETE:
{
- if ((res= delete_precheck(thd, tables)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= delete_precheck(thd, all_tables)))
break;
- res = mysql_delete(thd,tables, select_lex->where,
+ res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
select_lex->select_limit, select_lex->options);
if (thd->net.report_error)
@@ -2762,13 +2817,13 @@ unsent_create_error:
}
case SQLCOM_DELETE_MULTI:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
- TABLE_LIST *target_tbl;
uint table_count;
multi_delete *result;
- if ((res= multi_delete_precheck(thd, tables, &table_count)))
+ if ((res= multi_delete_precheck(thd, all_tables, &table_count)))
break;
/* condition will be TRUE on SP re-excuting */
@@ -2781,33 +2836,11 @@ unsent_create_error:
}
thd->proc_info="init";
- if ((res=open_and_lock_tables(thd,tables)))
+ if ((res= open_and_lock_tables(thd, all_tables)))
+ break;
+
+ if ((res= mysql_multi_delete_prepare(thd)))
break;
- /* Fix tables-to-be-deleted-from list to point at opened tables */
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next)
- {
- target_tbl->table= target_tbl->table_list->table;
- /*
- Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlaying SELECTs of it
- */
- for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
- un;
- un= un->next_unit())
- {
- if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
- un->check_updateable(target_tbl->table_list->db,
- target_tbl->table_list->real_name))
- {
- my_error(ER_UPDATE_TABLE_USED, MYF(0),
- target_tbl->table_list->real_name);
- res= -1;
- break;
- }
- }
- }
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
table_count)))
@@ -2833,9 +2866,10 @@ unsent_create_error:
}
case SQLCOM_DROP_TABLE:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!lex->drop_temporary)
{
- if (check_table_access(thd,DROP_ACL,tables,0))
+ if (check_table_access(thd, DROP_ACL, all_tables, 0))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
{
@@ -2856,16 +2890,18 @@ unsent_create_error:
if (thd->slave_thread)
lex->drop_if_exists= 1;
}
- res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
+ res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
+ lex->drop_temporary);
}
break;
case SQLCOM_DROP_INDEX:
- if (check_one_table_access(thd, INDEX_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
res= -1;
else
- res = mysql_drop_index(thd, tables, &lex->alter_info);
+ res = mysql_drop_index(thd, first_table, &lex->alter_info);
break;
case SQLCOM_SHOW_DATABASES:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
@@ -2964,40 +3000,42 @@ unsent_create_error:
res= mysqld_show_collations(thd,(lex->wild ? lex->wild->ptr() : NullS));
break;
case SQLCOM_SHOW_FIELDS:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
goto error;
#else
{
- char *db=tables->db;
+ char *db= first_table->db;
remove_escape(db); // Fix escaped '_'
- remove_escape(tables->real_name);
+ remove_escape(first_table->real_name);
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &tables->grant.privilege, 0, 0))
+ &first_table->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
+ if (grant_option && check_grant(thd, SELECT_ACL, first_table, 2, UINT_MAX, 0))
goto error;
- res= mysqld_show_fields(thd,tables,
+ res= mysqld_show_fields(thd, first_table,
(lex->wild ? lex->wild->ptr() : NullS),
lex->verbose);
break;
}
#endif
case SQLCOM_SHOW_KEYS:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
goto error;
#else
{
- char *db=tables->db;
+ char *db= first_table->db;
remove_escape(db); // Fix escaped '_'
- remove_escape(tables->real_name);
+ remove_escape(first_table->real_name);
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &tables->grant.privilege, 0, 0))
+ &first_table->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
+ if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
goto error;
- res= mysqld_show_keys(thd,tables);
+ res= mysqld_show_keys(thd, first_table);
break;
}
#endif
@@ -3007,12 +3045,13 @@ unsent_create_error:
case SQLCOM_LOAD:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
uint privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
if (!lex->local_file)
{
- if (check_access(thd,privilege | FILE_ACL,tables->db,0,0,0))
+ if (check_access(thd, privilege | FILE_ACL, first_table->db, 0, 0, 0))
goto error;
}
else
@@ -3023,19 +3062,20 @@ unsent_create_error:
send_error(thd,ER_NOT_ALLOWED_COMMAND);
goto error;
}
- if (check_one_table_access(thd, privilege, tables))
+ if (check_one_table_access(thd, privilege, all_tables))
goto error;
}
- res=mysql_load(thd, lex->exchange, tables, lex->field_list,
- lex->duplicates, (bool) lex->local_file, lex->lock_option);
+ res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
+ lex->duplicates, (bool) lex->local_file, lex->lock_option);
break;
}
case SQLCOM_SET_OPTION:
{
List<set_var_base> *lex_var_list= &lex->var_list;
- if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
- (res= open_and_lock_tables(thd,tables))))
+ if (all_tables &&
+ ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
+ (res= open_and_lock_tables(thd, all_tables))))
break;
if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
{
@@ -3071,17 +3111,20 @@ purposes internal to the MySQL server", MYF(0));
break;
case SQLCOM_LOCK_TABLES:
unlock_locked_tables(thd);
- if (check_db_used(thd,tables) || end_active_trans(thd))
+ if (check_db_used(thd, all_tables) || end_active_trans(thd))
goto error;
- if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables,0))
+ if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0))
goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
- if (!(res= open_and_lock_tables(thd, tables)))
+
+
+
+ if (!(res= open_and_lock_tables(thd, all_tables)))
{
#ifdef HAVE_QUERY_CACHE
if (thd->variables.query_cache_wlock_invalidate)
- query_cache.invalidate_locked_for_write(tables);
+ query_cache.invalidate_locked_for_write(first_table);
#endif /*HAVE_QUERY_CACHE*/
thd->locked_tables=thd->lock;
thd->lock=0;
@@ -3259,9 +3302,10 @@ purposes internal to the MySQL server", MYF(0));
case SQLCOM_GRANT:
{
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
- tables && tables->db ? tables->db : select_lex->db,
- tables ? &tables->grant.privilege : 0,
- tables ? 0 : 1,0))
+ ((first_table && first_table->db) ?
+ first_table->db : select_lex->db),
+ first_table ? &first_table->grant.privilege : 0,
+ first_table ? 0 : 1, 0))
goto error;
/*
@@ -3300,15 +3344,15 @@ purposes internal to the MySQL server", MYF(0));
user->host.str);
}
}
- if (tables)
+ if (first_table)
{
if (grant_option && check_grant(thd,
(lex->grant | lex->grant_tot_col |
GRANT_ACL),
- tables, 0, UINT_MAX, 0))
+ all_tables, 0, UINT_MAX, 0))
goto error;
- if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
- lex->grant,
+ if (!(res = mysql_table_grant(thd, all_tables, lex->users_list,
+ lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE)) &&
mysql_bin_log.is_open())
{
@@ -3355,14 +3399,14 @@ purposes internal to the MySQL server", MYF(0));
lex->no_write_to_binlog= 1;
case SQLCOM_FLUSH:
{
- if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
+ if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables))
goto error;
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
binlog or not.
*/
bool write_to_binlog;
- if (reload_acl_and_cache(thd, lex->type, tables, &write_to_binlog))
+ if (reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
send_error(thd, 0);
else
{
@@ -3397,27 +3441,30 @@ purposes internal to the MySQL server", MYF(0));
break;
#endif
case SQLCOM_HA_OPEN:
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL, all_tables, 0))
goto error;
- res = mysql_ha_open(thd, tables);
+ res= mysql_ha_open(thd, first_table);
break;
case SQLCOM_HA_CLOSE:
- if (check_db_used(thd,tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables))
goto error;
- res = mysql_ha_close(thd, tables);
+ res= mysql_ha_close(thd, first_table);
break;
case SQLCOM_HA_READ:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
/*
There is no need to check for table permissions here, because
if a user has no permissions to read a table, he won't be
able to open it (with SQLCOM_HA_OPEN) in the first place.
*/
- if (check_db_used(thd,tables))
+ if (check_db_used(thd, all_tables))
goto error;
- res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir,
- lex->insert_list, lex->ha_rkey_mode, select_lex->where,
- select_lex->select_limit, select_lex->offset_limit);
+ res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->backup_dir,
+ lex->insert_list, lex->ha_rkey_mode, select_lex->where,
+ select_lex->select_limit, select_lex->offset_limit);
break;
case SQLCOM_BEGIN:
@@ -3573,12 +3620,12 @@ purposes internal to the MySQL server", MYF(0));
LINT_INIT(smrx);
/* In case the arguments are subselects... */
- if (tables && ((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
- (res= open_and_lock_tables(thd, tables))))
+ if (all_tables &&
+ ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
+ (res= open_and_lock_tables(thd, all_tables))))
{
break;
}
- fix_tables_pointers(lex->all_selects_list);
#ifndef EMBEDDED_LIBRARY
/*
@@ -3764,6 +3811,23 @@ purposes internal to the MySQL server", MYF(0));
lex->wild->ptr() : NullS));
break;
}
+ case SQLCOM_CREATE_VIEW:
+ {
+ res= mysql_create_view(thd, thd->lex->create_view_mode);
+ break;
+ }
+ case SQLCOM_DROP_VIEW:
+ {
+ if (check_table_access(thd, DROP_ACL, all_tables, 0))
+ goto error;
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
+ res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
+ break;
+ }
default: /* Impossible */
send_ok(thd);
break;
@@ -3836,27 +3900,28 @@ error:
check_one_table_access()
thd Thread handler
privilege requested privelage
- tables table list of command
+ all_tables global table list of query
RETURN
0 - OK
1 - access denied, error is sent to client
*/
-int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
+int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
{
- if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
+ if (check_access(thd, privilege, all_tables->db,
+ &all_tables->grant.privilege, 0, 0))
return 1;
/* Show only 1 table for check_grant */
- if (grant_option && check_grant(thd, privilege, tables, 0, 1, 0))
+ if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0))
return 1;
/* Check rights on tables of subselect (if exists) */
TABLE_LIST *subselects_tables;
- if ((subselects_tables= tables->next))
+ if ((subselects_tables= all_tables->next_global))
{
- if ((check_table_access(thd, SELECT_ACL, subselects_tables,0)))
+ if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
return 1;
}
return 0;
@@ -4008,7 +4073,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
uint found=0;
ulong found_access=0;
TABLE_LIST *org_tables=tables;
- for (; tables ; tables=tables->next)
+ for (; tables; tables= tables->next_global)
{
if (tables->derived || (tables->table && (int)tables->table->tmp_table))
continue;
@@ -4046,7 +4111,7 @@ bool check_merge_table_access(THD *thd, char *db,
{
/* Check that all tables use the current database */
TABLE_LIST *tmp;
- for (tmp=table_list; tmp ; tmp=tmp->next)
+ for (tmp= table_list; tmp; tmp= tmp->next_local)
{
if (!tmp->db || !tmp->db[0])
tmp->db=db;
@@ -4060,7 +4125,7 @@ bool check_merge_table_access(THD *thd, char *db,
static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
- for (; tables ; tables=tables->next)
+ for (; tables; tables= tables->next_global)
{
if (!tables->db)
{
@@ -4154,6 +4219,7 @@ mysql_init_query(THD *thd, bool lexonly)
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
+ lex->view_list.empty();
lex->unit.next= lex->unit.master=
lex->unit.link_next= lex->unit.return_to=0;
lex->unit.prev= lex->unit.link_prev= 0;
@@ -4167,10 +4233,16 @@ mysql_init_query(THD *thd, bool lexonly)
lex->select_lex.init_order();
lex->select_lex.group_list.empty();
lex->describe= 0;
- lex->derived_tables= FALSE;
+ lex->derived_tables= 0;
+ lex->view_prepare_mode= FALSE;
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
+ lex->query_tables= 0;
+ lex->query_tables_last= &lex->query_tables;
+ lex->variables_used= 0;
+ lex->select_lex.parent_lex= lex;
+ lex->empty_field_list_on_rset= 0;
if (! lexonly)
{
thd->select_number= lex->select_lex.select_number= 1;
@@ -4215,6 +4287,7 @@ mysql_new_select(LEX *lex, bool move_down)
select_lex->select_number= ++lex->thd->select_number;
select_lex->init_query();
select_lex->init_select();
+ select_lex->parent_lex= lex;
if (move_down)
{
/* first select_lex of subselect or derived table */
@@ -4233,6 +4306,11 @@ mysql_new_select(LEX *lex, bool move_down)
}
else
{
+ if (lex->current_select->order_list.first && !lex->current_select->braces)
+ {
+ net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "ORDER BY");
+ return 1;
+ }
select_lex->include_neighbour(lex->current_select);
SELECT_LEX_UNIT *unit= select_lex->master_unit();
SELECT_LEX *fake= unit->fake_select_lex;
@@ -4299,6 +4377,8 @@ void mysql_init_multi_delete(LEX *lex)
lex->select_lex.select_limit= lex->unit.select_limit_cnt=
HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list);
+ lex->query_tables= 0;
+ lex->query_tables_last= &lex->query_tables;
}
@@ -4931,6 +5011,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
+ ptr->select_lex= thd->lex->current_select;
ptr->cacheable_table= 1;
if (use_index_arg)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
@@ -4944,7 +5025,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
tables ;
- tables=tables->next)
+ tables=tables->next_local)
{
if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
!strcmp(ptr->db, tables->db))
@@ -4954,7 +5035,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
}
}
- table_list.link_in_list((byte*) ptr, (byte**) &ptr->next);
+ table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
+ LEX *lex= thd->lex;
+ *(ptr->prev_global= lex->query_tables_last)= ptr;
+ lex->query_tables_last= &ptr->next_global;
DBUG_RETURN(ptr);
}
@@ -5210,9 +5294,9 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
- for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first ;
- tables ;
- tables=tables->next)
+ for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first;
+ tables;
+ tables= tables->next_local)
{
tables->lock_type= lock_type;
tables->updating= for_update;
@@ -5643,7 +5727,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
SYNOPSIS
multi_update_precheck()
thd Thread handler
- tables Global table list
+ tables Global/local table list (have to be the same)
RETURN VALUE
0 OK
@@ -5653,12 +5737,11 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
int multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("multi_update_precheck");
const char *msg= 0;
TABLE_LIST *table;
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
- TABLE_LIST *update_list= (TABLE_LIST*)select_lex->table_list.first;
+ DBUG_ENTER("multi_update_precheck");
if (select_lex->item_list.elements != lex->value_list.elements)
{
@@ -5669,7 +5752,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
- for (table= update_list; table; table= table->next)
+ for (table= tables; table; table= table->next_local)
{
if ((check_access(thd, UPDATE_ACL, table->db,
&table->grant.privilege, 0, 1) ||
@@ -5679,31 +5762,16 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
DBUG_RETURN(1);
- /*
- We assign following flag only to copy of table, because it will
- be checked only if query contains subqueries i.e. only if copy exists
- */
- if (table->table_list)
- table->table_list->table_in_update_from_clause= 1;
+ table->table_in_first_from_clause= 1;
}
/*
Is there tables of subqueries?
*/
if (&lex->select_lex != lex->all_selects_list)
{
- for (table= tables; table; table= table->next)
+ for (table= tables; table; table= table->next_global)
{
- if (table->table_in_update_from_clause)
- {
- /*
- If we check table by local TABLE_LIST copy then we should copy
- grants to global table list, because it will be used for table
- opening.
- */
- if (table->table_list)
- table->grant= table->table_list->grant;
- }
- else
+ if (!table->table_in_first_from_clause)
{
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
@@ -5732,7 +5800,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
SYNOPSIS
multi_delete_precheck()
thd Thread handler
- tables Global table list
+ tables Global/local table list
table_count Pointer to table counter
RETURN VALUE
@@ -5742,12 +5810,11 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
*/
int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
{
- DBUG_ENTER("multi_delete_precheck");
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
- TABLE_LIST *delete_tables= (TABLE_LIST *)select_lex->table_list.first;
TABLE_LIST *target_tbl;
+ DBUG_ENTER("multi_delete_precheck");
*table_count= 0;
@@ -5762,12 +5829,12 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0));
DBUG_RETURN(-1);
}
- for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next)
+ for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next_local)
{
(*table_count)++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
- for (walk= delete_tables; walk; walk= walk->next)
+ for (walk= tables; walk; walk= walk->next_local)
{
if (!my_strcasecmp(table_alias_charset,
target_tbl->alias, walk->alias) &&
@@ -5780,14 +5847,8 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
"MULTI DELETE");
DBUG_RETURN(-1);
}
- if (walk->derived)
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), target_tbl->real_name,
- "DELETE");
- DBUG_RETURN(-1);
- }
walk->lock_type= target_tbl->lock_type;
- target_tbl->table_list= walk; // Remember corresponding table
+ target_tbl->correspondent_table= walk; // Remember corresponding table
}
DBUG_RETURN(0);
}