Commit 8c6a02df authored by unknown's avatar unknown
Browse files

Fix for sp.test failure in --ps-protocol mode (2nd attempt).

Now we should call open_and_lock_tables() even if table list is empty -
to cache stored routines used by query and open and lock tables required
for their execution.


sql/sql_insert.cc:
  Now we should call open_and_lock_tables() even if table list is empty -
  to cache stored routines used by query and open and lock tables required
  for their execution.
sql/sql_prepare.cc:
  Now we should call open_and_lock_tables() even if table list is empty -
  to cache stored routines used by query and open and lock tables required
  for their execution. Thus we have to move most of functionality from 
  select_like_statement_test() to separate function to be able to reuse it
  for multi-update processing (for which tables are open and locked in 
  mysql_multi_update_prepare() call).
parent 08e23eb6
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -217,8 +217,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
    }
    if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
    {
      res= 0;
      if (table_list->next_global)			/* if sub select */
      /*
        Open tables used for sub-selects or in stored functions, will also
        cache these functions.
      */
      res= open_and_lock_tables(thd, table_list->next_global);
      /*
	First is not processed by open_and_lock_tables() => we need set
+67 −32
Original line number Diff line number Diff line
@@ -1230,7 +1230,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
  if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
    DBUG_RETURN(TRUE);

  if (tables && open_and_lock_tables(thd, tables))
  if (open_and_lock_tables(thd, tables))
  {
    DBUG_RETURN(TRUE);
  }
@@ -1261,12 +1261,12 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
  List_iterator_fast<set_var_base> it(*var_list);
  THD *thd= stmt->thd;
  set_var_base *var;
  bool res= 0;
  bool res;

  if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
    DBUG_RETURN(TRUE);

  if (tables && (res= open_and_lock_tables(thd, tables)))
  if ((res= open_and_lock_tables(thd, tables)))
    goto error;
  while ((var= it++))
  {
@@ -1287,30 +1287,30 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
  Check internal SELECT of the prepared command

  SYNOPSIS
    select_like_statement_test()
      stmt              - prepared table handler
      tables            - global list of tables
    select_like_stmt_test()
      stmt                      - prepared statement handler
      specific_prepare          - function of command specific prepare
      setup_tables_done_option  - options to be passed to LEX::unit.prepare()

  NOTE
    This function won't directly open tables used in select. They should
    be opened either by calling function (and in this case you probably
    should use select_like_stmt_test_with_open_n_lock()) or by
    "specific_prepare" call (like this happens in case of multi-update).

  RETURN VALUE
    FALSE success
    TRUE  error
*/
static bool select_like_statement_test(Prepared_statement *stmt,
                                       TABLE_LIST *tables,

static bool select_like_stmt_test(Prepared_statement *stmt,
                                  bool (*specific_prepare)(THD *thd),
                                  ulong setup_tables_done_option)
{
  DBUG_ENTER("select_like_statement_test");
  DBUG_ENTER("select_like_stmt_test");
  THD *thd= stmt->thd;
  LEX *lex= stmt->lex;
  bool res= 0;

  /* check that tables was not opened during conversion from usual update */
  if (tables &&
      (!tables->table && !tables->view) &&
      (res= open_and_lock_tables(thd, tables)))
    goto end;
  bool res= FALSE;

  if (specific_prepare && (res= (*specific_prepare)(thd)))
    goto end;
@@ -1328,6 +1328,44 @@ static bool select_like_statement_test(Prepared_statement *stmt,
}


/*
  Check internal SELECT of the prepared command (with opening and
  locking tables used).

  SYNOPSIS
    select_like_stmt_test_with_open_n_lock()
      stmt                      - prepared statement handler
      tables                    - list of tables to be opened and locked
                                  before calling specific_prepare function
      specific_prepare          - function of command specific prepare
      setup_tables_done_option  - options to be passed to LEX::unit.prepare()

  RETURN VALUE
    FALSE success
    TRUE  error
*/

static bool
select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt,
                                       TABLE_LIST *tables,
                                       bool (*specific_prepare)(THD *thd),
                                       ulong setup_tables_done_option)
{
  DBUG_ENTER("select_like_stmt_test_with_open_n_lock");

  /*
    We should not call LEX::unit.cleanup() after this open_and_lock_tables()
    call because we don't allow prepared EXPLAIN yet so derived tables will
    clean up after themself.
  */
  if (open_and_lock_tables(stmt->thd, tables))
    DBUG_RETURN(TRUE);

  DBUG_RETURN(select_like_stmt_test(stmt, specific_prepare,
                                    setup_tables_done_option));
}


/*
  Validate and prepare for execution CREATE TABLE statement

@@ -1358,7 +1396,7 @@ static int mysql_test_create_table(Prepared_statement *stmt)
      select_lex->item_list.elements)
  {
    select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
    res= select_like_statement_test(stmt, tables, 0, 0);
    res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
    select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
  }

@@ -1389,11 +1427,8 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt,
  /* if we switched from normal update, rights are checked */
  if (!converted && multi_update_precheck(stmt->thd, tables))
    return TRUE;
  /*
    here we do not pass tables for opening, tables will be opened and locked
    by mysql_multi_update_prepare
  */
  return select_like_statement_test(stmt, 0, &mysql_multi_update_prepare,

  return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
                               OPTION_SETUP_TABLES_DONE);
}

@@ -1422,7 +1457,7 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
  uint fake_counter;
  if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
    return res;
  if ((res= select_like_statement_test(stmt, tables,
  if ((res= select_like_stmt_test_with_open_n_lock(stmt, tables,
                                                   &mysql_multi_delete_prepare,
                                                   OPTION_SETUP_TABLES_DONE)))
    return res;
@@ -1500,7 +1535,7 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
  first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
  DBUG_ASSERT(first_local_table != 0);

  res= select_like_statement_test(stmt, tables,
  res= select_like_stmt_test_with_open_n_lock(stmt, tables,
                                              &mysql_insert_select_prepare_tester,
                                              OPTION_SETUP_TABLES_DONE);
  /* revert changes  made by mysql_insert_select_prepare_tester */