summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2005-01-04 18:04:16 +0200
committerbell@sanja.is.com.ua <>2005-01-04 18:04:16 +0200
commita8a5f3590cb1badf544f7454d783a71a1bdf6dbc (patch)
tree614f6803a8c639e656f89a70e02feda14d66d919 /sql
parenta99921fb3949fec0a2c7eaa2f96ad9ab071f53f3 (diff)
downloadmariadb-git-a8a5f3590cb1badf544f7454d783a71a1bdf6dbc.tar.gz
fixed bugs in view code with prepared statemnts
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_base.cc32
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc79
-rw-r--r--sql/sql_update.cc10
-rw-r--r--sql/sql_view.cc24
-rw-r--r--sql/table.cc11
8 files changed, 116 insertions, 48 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ba00c1d3fa7..25f26938e84 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3317,7 +3317,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
{
GRANT_TABLE *grant_table;
if (!(~table->grant.privilege & want_access) ||
- table->derived || table->schema_table)
+ table->derived || table->schema_table || table->belong_to_view)
{
/*
It is subquery in the FROM clause. VIEW set table->derived after
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0b0bf6df7ad..87e4f5df1cc 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2089,7 +2089,12 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(WRONG_GRANT);
#endif
if (thd->lex->current_select->no_wrap_view_item)
- *ref= trans[i].item;
+ {
+ if (register_tree_change)
+ thd->change_item_tree(ref, trans[i].item);
+ else
+ *ref= trans[i].item;
+ }
else
{
Item_ref *item_ref= new Item_ref(&trans[i].item,
@@ -2098,6 +2103,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
/* as far as Item_ref have defined reference it do not need tables */
if (register_tree_change && item_ref)
thd->change_item_tree(ref, item_ref);
+ else if (item_ref)
+ *ref= item_ref;
}
DBUG_RETURN((Field*) view_ref_found);
}
@@ -2944,6 +2951,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
TABLE_LIST *last;
TABLE_LIST *embedding;
TABLE *table= tables->table;
+ bool alias_used= 0;
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
tables->alias) &&
@@ -3016,6 +3024,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
{
iterator= &view_iter;
view= 1;
+ alias_used= my_strcasecmp(table_alias_charset,
+ tables->real_name, tables->alias);
}
else
{
@@ -3037,15 +3047,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
&not_used_field_index, TRUE))
{
Item *item= iterator->item(thd);
- if (!found++)
- (void) it->replace(item); // Replace '*'
- else
- it->after(item);
if (view && !thd->lex->current_select->no_wrap_view_item)
{
item= new Item_ref(it->ref(), tables->view_name.str,
field_name);
}
+ if (!found++)
+ (void) it->replace(item); // Replace '*'
+ else
+ it->after(item);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges)
{
@@ -3099,9 +3109,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
else if (allocate_view_names &&
thd->lex->current_select->first_execution)
{
- Item_field *item= new Item_field(thd->strdup(tables->view_db.str),
- thd->strdup(tables->view_name.str),
- thd->strdup(field_name));
+ Item_field *item;
+ if (alias_used)
+ item= new Item_field(0,
+ thd->strdup(tables->alias),
+ thd->strdup(field_name));
+ else
+ item= new Item_field(thd->strdup(tables->view_db.str),
+ thd->strdup(tables->view_name.str),
+ thd->strdup(field_name));
/*
during cleunup() this item will be put in list to replace
expression from VIEW
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 45b62ef8d83..dc80081bbc8 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -138,7 +138,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
}
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
+ table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
#endif
if (check_key_in_view(thd, table_list) ||
@@ -1720,8 +1720,6 @@ bool delayed_insert::handle_inserts(void)
bool mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
- TABLE_LIST *first_select_table=
- (TABLE_LIST*) lex->select_lex.table_list.first;
TABLE_LIST *first_select_leaf_table;
int res;
DBUG_ENTER("mysql_insert_select_prepare");
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 442d398889f..60caa3ff421 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4330,7 +4330,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
TABLE_LIST *org_tables=tables;
for (; tables; tables= tables->next_global)
{
- if (tables->derived || tables->schema_table ||
+ if (tables->derived || tables->schema_table || tables->belong_to_view ||
(tables->table && (int)tables->table->tmp_table) ||
my_tz_check_n_skip_implicit_tables(&tables,
thd->lex->time_zone_tables_used))
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 88f90e393f6..b65d0e137ce 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -968,6 +968,9 @@ static int mysql_test_update(Prepared_statement *stmt,
THD *thd= stmt->thd;
uint table_count= 0;
SELECT_LEX *select= &stmt->lex->select_lex;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint want_privilege;
+#endif
DBUG_ENTER("mysql_test_update");
if (update_precheck(thd, table_list))
@@ -990,17 +993,29 @@ static int mysql_test_update(Prepared_statement *stmt,
return 2;
}
+ /*
+ thd->fill_derived_tables() is false here for sure (because it is
+ preparation of PS, so we even do not check it
+ */
if (lock_tables(thd, table_list, table_count) ||
- mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
- (thd->fill_derived_tables() &&
- mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ mysql_handle_derived(thd->lex, &mysql_derived_prepare))
DBUG_RETURN(1);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* TABLE_LIST contain right privilages request */
+ want_privilege= table_list->grant.want_privilege;
+#endif
+
if (!(res= mysql_prepare_update(thd, table_list,
&select->where,
select->order_list.elements,
(ORDER *) select->order_list.first)))
{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ table_list->grant.want_privilege=
+ table_list->table->grant.want_privilege=
+ want_privilege;
+#endif
thd->lex->select_lex.no_wrap_view_item= 1;
if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0))
{
@@ -1010,6 +1025,12 @@ static int mysql_test_update(Prepared_statement *stmt,
else
{
thd->lex->select_lex.no_wrap_view_item= 0;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* Check values */
+ table_list->grant.want_privilege=
+ table_list->table->grant.want_privilege=
+ (SELECT_ACL & ~table_list->table->grant.privilege);
+#endif
if (setup_fields(thd, 0, table_list,
stmt->lex->value_list, 0, 0, 0))
res= 1;
@@ -1391,12 +1412,39 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
/*
+ Wrapper for mysql_insert_select_prepare, to make change of local tables
+ after open_and_lock_tables() call.
+
+ SYNOPSIS
+ mysql_insert_select_prepare_tester()
+ thd thread handler
+
+ NOTE: we need remove first local tables after open_and_lock_tables,
+ because mysql_handle_derived use local tables lists
+*/
+
+static bool mysql_insert_select_prepare_tester(THD *thd)
+{
+ SELECT_LEX *first_select= &thd->lex->select_lex;
+ /* Skip first table, which is the table we are inserting in */
+ first_select->table_list.first= (byte*)((TABLE_LIST*)first_select->
+ table_list.first)->next_local;
+ /*
+ insert/replace from SELECT give its SELECT_LEX for SELECT,
+ and item_list belong to SELECT
+ */
+ first_select->resolve_mode= SELECT_LEX::SELECT_MODE;
+ mysql_insert_select_prepare(thd);
+}
+
+
+/*
Validate and prepare for execution INSERT ... SELECT statement
SYNOPSIS
mysql_test_insert_select()
stmt prepared statemen handler
- tables list of tables queries
+ tables list of tables of query
RETURN VALUE
0 success
@@ -1411,26 +1459,23 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
LEX *lex= stmt->lex;
TABLE_LIST *first_local_table;
- if ((res= insert_precheck(stmt->thd, tables)))
- return res;
- first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
- DBUG_ASSERT(first_local_table != 0);
- /* Skip first table, which is the table we are inserting in */
- lex->select_lex.table_list.first= (byte*) first_local_table->next_local;
if (tables->table)
{
// don't allocate insert_values
tables->table->insert_values=(byte *)1;
}
- /*
- 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= select_like_statement_test(stmt, tables, &mysql_insert_select_prepare,
+ if ((res= insert_precheck(stmt->thd, tables)))
+ return res;
+
+ /* store it, because mysql_insert_select_prepare_tester change it */
+ first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
+ DBUG_ASSERT(first_local_table != 0);
+
+ res= select_like_statement_test(stmt, tables,
+ &mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE);
- /* revert changes*/
+ /* revert changes made by mysql_insert_select_prepare_tester */
lex->select_lex.table_list.first= (byte*) first_local_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
return res;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5ca25bbac3e..5e7bdf69dbb 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -170,10 +170,8 @@ int mysql_update(THD *thd,
table->quick_keys.clear_all();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* In case of view TABLE_LIST contain right privilages request */
- want_privilege= (table_list->view ?
- table_list->grant.want_privilege :
- table->grant.want_privilege);
+ /* TABLE_LIST contain right privilages request */
+ want_privilege= table_list->grant.want_privilege;
#endif
if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
DBUG_RETURN(1);
@@ -221,7 +219,7 @@ int mysql_update(THD *thd,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
+ (SELECT_ACL & ~~table->grant.privilege);
#endif
if (setup_fields(thd, 0, table_list, values, 1, 0, 0))
{
@@ -715,7 +713,7 @@ bool mysql_multi_update_prepare(THD *thd)
}
/* Check access privileges for table */
- if (!tl->derived)
+ if (!tl->derived && !tl->belong_to_view)
{
uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
if (!using_lock_tables)
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index bafb57c44b0..e982eb8e6be 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -680,18 +680,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
hash_free(&lex->spfuns);
/*
- mark to avoid temporary table using and put view reference and find
- last view table
- */
- for (tbl= view_tables;
- tbl;
- tbl= (view_tables_tail= tbl)->next_global)
- {
- tbl->skip_temporary= 1;
- tbl->belong_to_view= top_view;
- }
-
- /*
check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
underlying tables
*/
@@ -710,6 +698,18 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
goto err;
}
+ /*
+ mark to avoid temporary table using and put view reference and find
+ last view table
+ */
+ for (tbl= view_tables;
+ tbl;
+ tbl= (view_tables_tail= tbl)->next_global)
+ {
+ tbl->skip_temporary= 1;
+ tbl->belong_to_view= top_view;
+ }
+
/* move SQL_NO_CACHE & Co to whole query */
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
lex->safe_to_cache_query);
diff --git a/sql/table.cc b/sql/table.cc
index e9b89d6b124..12862d21ac0 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1726,6 +1726,9 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
}
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
goto err;
+ if (check_option && !check_option->fixed &&
+ check_option->fix_fields(thd, ancestor, &where))
+ goto err;
restore_want_privilege();
/* WHERE/ON resolved => we can rename fields */
@@ -1873,11 +1876,19 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
/* full text function moving to current select */
if (view->select_lex.ftfunc_list->elements)
{
+ Item_arena *arena= thd->current_arena, backup;
+ if (arena->is_conventional())
+ arena= 0; // For easier test
+ else
+ thd->set_n_backup_item_arena(arena, &backup);
+
Item_func_match *ifm;
List_iterator_fast<Item_func_match>
li(*(view->select_lex.ftfunc_list));
while ((ifm= li++))
current_select_save->ftfunc_list->push_front(ifm);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
}
ok: