Commit 34f313ee authored by unknown's avatar unknown
Browse files

fixed bugs in view code with prepared statemnts


sql/sql_acl.cc:
  block checking view underlying tables
sql/sql_base.cc:
  item registration fixed
  fixed non registred item resolving
  fixed result of outo-merge
  fixed creation reference if alias used
sql/sql_insert.cc:
  layout fixed
  removed unused variable
sql/sql_parse.cc:
  block checking view underlying tables
sql/sql_prepare.cc:
  make preparation check same as usual check
sql/sql_update.cc:
  made want_privilege assignment simplier
  block checking view underlying tables
sql/sql_view.cc:
  belong_to_view assignmebt moved after privileges check
sql/table.cc:
  check option fix field added
  arena management added
parent 592ffbcd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+24 −8
Original line number Diff line number Diff line
@@ -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)
	{
	  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,7 +3109,13 @@ 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),
	  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));
          /*
+1 −3
Original line number Diff line number Diff line
@@ -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");
+1 −1
Original line number Diff line number Diff line
@@ -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))
+62 −17
Original line number Diff line number Diff line
@@ -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;
@@ -1390,13 +1411,40 @@ 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;
Loading