Commit 90b2daa7 authored by unknown's avatar unknown
Browse files

Ensure we free all items for prepared statements

Before the fix in ~Prepared_statments we got a memory leak when executing mysql_client_test.test
Note that test 'variables.test' fails.
This will be fixed when Jimw pushes the fix for Bug 10351


mysys/default.c:
  Fixed typo
sql/item.cc:
  More debugging information
sql/sql_prepare.cc:
  More debugging information
  Ensure we free all items for prepared statements
  Before the fix in ~Prepared_statments we got a memory leak when executing mysql_client_test.test
parent 833a5ce0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1023,7 +1023,7 @@ static void init_default_directories()
          }
          else
          {
            /' No parent directory (strange). Use current dir + '\' '*/
            /* No parent directory (strange). Use current dir + '\' */
            last[1]= 0;
          }
          break;
+2 −0
Original line number Diff line number Diff line
@@ -2188,6 +2188,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)

void Item_param::reset()
{
  DBUG_ENTER("Item_param::reset");
  /* Shrink string buffer if it's bigger than max possible CHAR column */
  if (str_value.alloced_length() > MAX_CHAR_WIDTH)
    str_value.free();
@@ -2212,6 +2213,7 @@ void Item_param::reset()
    DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_*
    methods).
  */
  DBUG_VOID_RETURN;
}


+20 −4
Original line number Diff line number Diff line
@@ -1682,10 +1682,12 @@ static bool init_param_array(Prepared_statement *stmt)

static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd)
{
  DBUG_ENTER("cleanup_stmt_and_thd_after_use");
  stmt->lex->unit.cleanup();
  cleanup_items(stmt->free_list);
  thd->rollback_item_tree_changes();
  thd->cleanup_after_query();
  DBUG_VOID_RETURN;
}

/*
@@ -1982,7 +1984,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
  if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
    DBUG_VOID_RETURN;

  DBUG_PRINT("exec_query:", ("%s", stmt->query));
  DBUG_PRINT("exec_query", ("%s", stmt->query));
  DBUG_PRINT("info",("stmt: %p", stmt));

  /* Check if we got an error when sending long data */
  if (stmt->state == Query_arena::ERROR)
@@ -2125,6 +2128,8 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
    DBUG_VOID_RETURN;
  }

  DBUG_PRINT("info",("stmt: %p", stmt));

  /* Must go before setting variables, as it clears thd->user_var_events */
  mysql_reset_thd_for_next_command(thd);
  thd->set_n_backup_statement(stmt, &stmt_backup);
@@ -2445,19 +2450,26 @@ void Prepared_statement::setup_set_params()

Prepared_statement::~Prepared_statement()
{
  DBUG_ENTER("Prepared_statement::~Prepared_statement");
  DBUG_PRINT("enter",("stmt: %p  cursor: %p", this, cursor));
  if (cursor)
  {
    if (cursor->is_open())
    {
      cursor->close(FALSE);
      free_items();
      cleanup_items(free_list);
      thd->rollback_item_tree_changes();
      free_root(cursor->mem_root, MYF(0));
    }
    cursor->Cursor::~Cursor();
  }
  else
  /*
    We have to call free on the items even if cleanup is called as some items,
    like Item_param, don't free everything until free_items()
  */
  free_items();
  delete lex->result;
  DBUG_VOID_RETURN;
}


@@ -2469,6 +2481,9 @@ Query_arena::Type Prepared_statement::type() const

void Prepared_statement::close_cursor()
{
  DBUG_ENTER("Prepared_statement::close_cursor");
  DBUG_PRINT("enter",("stmt: %p", this));

  if (cursor && cursor->is_open())
  {
    thd->change_list= cursor->change_list;
@@ -2483,4 +2498,5 @@ void Prepared_statement::close_cursor()
    mysql_stmt_send_long_data() call.
  */
  reset_stmt_params(this);
  DBUG_VOID_RETURN;
}