[Commits] 25ff319: CCCC

Oleksandr Byelkin sanja at mariadb.com
Tue Sep 20 22:40:19 EEST 2016


revision-id: 25ff31918e305886562556ab5df113f93a979458 (mariadb-10.1.8-265-g25ff319)
parent(s): 56caf0b96a94699cd84498d21523c78ff6f803f3
committer: Oleksandr Byelkin
timestamp: 2016-09-20 21:40:19 +0200
message:

CCCC

---
 include/mysql.h.pp        |   3 +-
 include/mysql_com.h       |   3 +-
 sql/item.cc               | 100 +++++++++++++++++++++++++++++++++++++---------
 sql/item.h                |  35 ++++++++++++++--
 sql/share/errmsg-utf8.txt |   5 +++
 sql/sql_class.cc          |  16 +++++++-
 sql/sql_error.h           |   5 ++-
 sql/sql_insert.cc         |  70 ++++++++++++++++++++++++++++++--
 sql/sql_parse.cc          |  14 +++----
 sql/sql_prepare.cc        |  47 ++++++++++++----------
 sql/sql_update.cc         |   4 ++
 11 files changed, 243 insertions(+), 59 deletions(-)

diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 1a04116..c985792 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -10,8 +10,7 @@ enum enum_server_command
   COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
   COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
   COM_MDB_GAP_BEG,
-  COM_MDB_GAP_END=249,
-  COM_STMT_BULK_EXECUTE=250,
+  COM_MDB_GAP_END=250,
   COM_SLAVE_WORKER=251,
   COM_SLAVE_IO=252,
   COM_SLAVE_SQL=253,
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 9a4127c..b3f2be1 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -113,8 +113,7 @@ enum enum_server_command
   COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
   /* don't forget to update const char *command_name[] in sql_parse.cc */
   COM_MDB_GAP_BEG,
-  COM_MDB_GAP_END=249,
-  COM_STMT_BULK_EXECUTE=250,
+  COM_MDB_GAP_END=250,
   COM_SLAVE_WORKER=251,
   COM_SLAVE_IO=252,
   COM_SLAVE_SQL=253,
diff --git a/sql/item.cc b/sql/item.cc
index 51ff8b5..2ac95b8 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -724,7 +724,9 @@ Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg,
 		       const char *field_name_arg)
   :Item_result_field(thd), orig_db_name(db_name_arg),
    orig_table_name(table_name_arg),
-   orig_field_name(field_name_arg), context(context_arg),
+   orig_field_name(field_name_arg),
+   default_value_target(0),
+   context(context_arg),
    db_name(db_name_arg), table_name(table_name_arg),
    field_name(field_name_arg),
    alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
@@ -737,7 +739,9 @@ Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg,
 Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_arg)
   :Item_result_field(thd), orig_db_name(NullS),
    orig_table_name(view_arg->table_name),
-   orig_field_name(field_name_arg), context(&view_arg->view->select_lex.context),
+   orig_field_name(field_name_arg),
+   default_value_target(0),
+   context(&view_arg->view->select_lex.context),
    db_name(NullS), table_name(view_arg->alias),
    field_name(field_name_arg),
    alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
@@ -756,6 +760,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
    orig_db_name(item->orig_db_name),
    orig_table_name(item->orig_table_name), 
    orig_field_name(item->orig_field_name),
+   default_value_target(item->default_value_target),
    context(item->context),
    db_name(item->db_name),
    table_name(item->table_name),
@@ -784,6 +789,7 @@ void Item_ident::cleanup()
     */
     can_be_depended= MY_TEST(depended_from);
   }
+  default_value_target= NULL;
   DBUG_VOID_RETURN;
 }
 
@@ -812,6 +818,13 @@ bool Item_ident::collect_outer_ref_processor(void *param)
   return FALSE;
 }
 
+void Item_ident::set_default_value_target(Item *item)
+{
+  if ((default_value_target= item) && fixed &&
+      type() == FIELD_ITEM)
+    default_value_target->set_default_value_source(((Item_field *)this)->
+                                                   field);
+}
 
 /**
   Store the pointer to this item field into a list if not already there.
@@ -2530,6 +2543,10 @@ void Item_field::set_field(Field *field_par)
   max_length= adjust_max_effective_column_length(field_par, max_length);
 
   fixed= 1;
+  if (default_value_target != 0)
+  {
+    default_value_target->set_default_value_source(field);
+  }
   if (field->table->s->tmp_table == SYSTEM_TMP_TABLE)
     any_privileges= 0;
 }
@@ -3223,7 +3240,8 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg):
   Item_basic_value(thd),
   Rewritable_query_parameter(pos_in_query_arg, 1),
   Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
-  state(NO_VALUE), indicators(0),
+  state(NO_VALUE), default_value_ref(NULL), default_value_source(NULL),
+  indicators(0), indicator(STMT_INDICATOR_NONE),
   /* Don't pretend to be a literal unless value for this item is set. */
   item_type(PARAM_ITEM),
   set_param_func(default_set_param_func),
@@ -3532,6 +3550,9 @@ void Item_param::reset()
     DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_*
     methods).
   */
+
+  default_value_source= NULL;
+  default_value_ref= NULL;
   DBUG_VOID_RETURN;
 }
 
@@ -3915,6 +3936,9 @@ Item_param::set_param_type_and_swap_value(Item_param *src)
   null_value= src->null_value;
   state= src->state;
   value= src->value;
+  default_value_ref= src->default_value_ref;
+  default_value_source= src->default_value_source;
+
 
   decimal_value.swap(src->decimal_value);
   str_value.swap(src->str_value);
@@ -3922,6 +3946,30 @@ Item_param::set_param_type_and_swap_value(Item_param *src)
 }
 
 
+bool Item_param::set_default(bool can_be_missed)
+{
+  if (!default_value_ref)
+  {
+    if (can_be_missed)
+      return FALSE;
+    my_message(ER_INVALID_DEFAULT_PARAM,
+               ER_THD(current_thd, ER_INVALID_DEFAULT_PARAM), MYF(0));
+    return TRUE;
+  }
+  THD *thd= default_value_ref->table->in_use;
+  if (!default_value_source)
+  {
+    default_value_source= new (thd->mem_root)
+      Item_default_value(thd, &thd->lex->select_lex.context, default_value_ref);
+    if (!default_value_source ||
+        default_value_source->fix_fields(thd, (Item **)&default_value_source))
+      return TRUE;
+    bitmap_set_bit(default_value_ref->table->read_set,
+                   default_value_ref->field_index);
+  }
+  return set_value(thd, NULL, (Item**)&default_value_source);
+}
+
 /**
   This operation is intended to store some item value in Item_param to be
   used later.
@@ -4080,6 +4128,17 @@ bool Item_param::append_for_log(THD *thd, String *str)
   return str->append(*val);
 }
 
+
+bool Item_param::walk(Item_processor processor, bool walk_subquery, void *arg)
+{
+  if (default_value_source &&
+      default_value_source->walk(processor, walk_subquery, arg))
+  {
+    return TRUE;
+  }
+  return (this->*processor)(arg);
+}
+
 /****************************************************************************
   Item_copy
 ****************************************************************************/
@@ -7238,6 +7297,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
         Item_field* fld;
         if (!(fld= new (thd->mem_root) Item_field(thd, from_field)))
           goto error;
+        fld->set_default_value_target(default_value_target);
         thd->change_item_tree(reference, fld);
         mark_as_dependent(thd, last_checked_context->select_lex,
                           current_sel, fld, fld);
@@ -8424,36 +8484,38 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
 bool Item_default_value::fix_fields(THD *thd, Item **items)
 {
   Item *real_arg;
-  Item_field *field_arg;
   Field *def_field;
   DBUG_ASSERT(fixed == 0);
 
-  if (!arg)
+  if (!arg && !arg_fld)
   {
     fixed= 1;
     return FALSE;
   }
-  if (!arg->fixed && arg->fix_fields(thd, &arg))
-    goto error;
+  if (arg)
+  {
+    if (!arg->fixed && arg->fix_fields(thd, &arg))
+      goto error;
 
 
-  real_arg= arg->real_item();
-  if (real_arg->type() != FIELD_ITEM)
-  {
-    my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
-    goto error;
-  }
+    real_arg= arg->real_item();
+    if (real_arg->type() != FIELD_ITEM)
+    {
+      my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
+      goto error;
+    }
 
-  field_arg= (Item_field *)real_arg;
-  if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
+    arg_fld= ((Item_field *)real_arg)->field;
+  }
+  if ((arg_fld->flags & NO_DEFAULT_VALUE_FLAG))
   {
-    my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
+    my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg_fld->field_name);
     goto error;
   }
-  if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
+  if (!(def_field= (Field*) thd->alloc(arg_fld->size_of())))
     goto error;
-  memcpy((void *)def_field, (void *)field_arg->field,
-         field_arg->field->size_of());
+  memcpy((void *)def_field, (void *)arg_fld,
+         arg_fld->size_of());
   def_field->move_field_offset((my_ptrdiff_t)
                                (def_field->table->s->default_values -
                                 def_field->table->record[0]));
diff --git a/sql/item.h b/sql/item.h
index 7e9cfbb..100e77a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1872,6 +1872,8 @@ class Item: public Value_source,
   {
     marker &= ~EXTRACTION_MASK;
   }
+
+  virtual void set_default_value_source(Field *fld) {};
 };
 
 
@@ -2351,6 +2353,8 @@ class Item_ident :public Item_result_field
   const char *orig_table_name;
   const char *orig_field_name;
 
+  Item *default_value_target;
+
 public:
   Name_resolution_context *context;
   const char *db_name;
@@ -2395,6 +2399,7 @@ class Item_ident :public Item_result_field
   virtual void print(String *str, enum_query_type query_type);
   virtual bool change_context_processor(void *cntx)
     { context= (Name_resolution_context *)cntx; return FALSE; }
+  void set_default_value_target(Item *item);
   /**
     Collect outer references
   */
@@ -2702,6 +2707,9 @@ class Item_null_result :public Item_null
   }
 };
 
+
+class Item_default_value;
+
 /*
   Item represents one placeholder ('?') of prepared statement
 
@@ -2727,11 +2735,14 @@ class Item_param :public Item_basic_value,
     DECIMAL_VALUE
   } state;
 
+  Field *default_value_ref;
+  Item_default_value *default_value_source;
   /*
     Used for bulk protocol. Indicates if we should expect
     indicators byte before value of the parameter
   */
   my_bool indicators;
+  uint indicator;
 
   /*
     A buffer for string and long data values. Historically all allocated
@@ -2790,6 +2801,10 @@ class Item_param :public Item_basic_value,
   bool get_date(MYSQL_TIME *tm, ulonglong fuzzydate);
   int  save_in_field(Field *field, bool no_conversions);
 
+  virtual void set_default_value_source(Field *fld)
+  { default_value_ref= fld; }
+
+  bool set_default(bool can_be_missed);
   void set_null();
   void set_int(longlong i, uint32 max_length_arg);
   void set_double(double i);
@@ -2833,8 +2848,8 @@ class Item_param :public Item_basic_value,
     constant, assert otherwise. This method is called only if
     basic_const_item returned TRUE.
   */
-  Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
   Item *clone_item(THD *thd);
+  Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
   /*
     Implement by-value equality evaluation if parameter value
     is set and is a basic constant (integer, real or string).
@@ -2857,11 +2872,20 @@ class Item_param :public Item_basic_value,
 
   virtual void set_out_param_info(Send_field *info);
 
+  bool fix_fields(THD *thd, Item **ref)
+  {
+    if (state == NO_VALUE && indicator == STMT_INDICATOR_DEFAULT &&
+        set_default(FALSE))
+      return TRUE;
+    return Item_basic_value::fix_fields(thd, ref);
+  }
+
 public:
   virtual const Send_field *get_out_param_info() const;
 
   virtual void make_field(THD *thd, Send_field *field);
 
+  virtual bool walk(Item_processor processor, bool walk_subquery, void *arg);
 private:
   Send_field *m_out_param_info;
 };
@@ -4986,14 +5010,19 @@ class Item_default_value : public Item_field
   void calculate();
 public:
   Item *arg;
+  Field *arg_fld;
   Item_default_value(THD *thd, Name_resolution_context *context_arg)
     :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
                (const char *)NULL),
-     arg(NULL) {}
+     arg(NULL), arg_fld(NULL) {}
   Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a)
     :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
                 (const char *)NULL),
-     arg(a) {}
+     arg(a), arg_fld(NULL) {}
+  Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a)
+    :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
+                (const char *)NULL),
+     arg(NULL), arg_fld(a) {}
   enum Type type() const { return DEFAULT_VALUE_ITEM; }
   bool eq(const Item *item, bool binary_cmp) const;
   bool fix_fields(THD *, Item **);
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 4efc1bd..aeb6502 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7226,3 +7226,8 @@ ER_EXPRESSION_REFERS_TO_UNINIT_FIELD 01000
 ER_PARTITION_DEFAULT_ERROR
         eng "Only one DEFAULT partition allowed"
         ukr "Припустимо мати тільки один DEFAULT розділ" 
+ER_INVALID_DEFAULT_PARAM
+        eng "Default value is not supported for such parameter usage"
+        ukr "Значення за замовчуванням не підтримано для цього випадку використання параьетра"
+ER_BINLOG_NON_SUPPORTED_BULK
+        eng "Only row based replication supported for bulk operations"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 887b153..08f8a16 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -5767,6 +5767,17 @@ int THD::decide_logging_format(TABLE_LIST *tables)
       !(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
         !binlog_filter->db_ok(db)))
   {
+
+    if (is_bulk_op())
+    {
+      if (wsrep_binlog_format() == BINLOG_FORMAT_STMT)
+      {
+        my_error(ER_BINLOG_NON_SUPPORTED_BULK, MYF(0));
+        DBUG_PRINT("info",
+                   ("decision: no logging since an error was generated"));
+        DBUG_RETURN(-1);
+      }
+    }
     /*
       Compute one bit field with the union of all the engine
       capabilities, and one with the intersection of all the engine
@@ -6025,7 +6036,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
         */
         my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0));
       }
-      else if (wsrep_binlog_format() == BINLOG_FORMAT_ROW &&
+      else if ((wsrep_binlog_format() == BINLOG_FORMAT_ROW || is_bulk_op()) &&
                sqlcom_can_generate_row_events(this))
       {
         /*
@@ -6098,7 +6109,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
       else
       {
         if (lex->is_stmt_unsafe() || lex->is_stmt_row_injection()
-            || (flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
+            || (flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0 ||
+            is_bulk_op())
         {
           /* log in row format! */
           set_current_stmt_binlog_format_row_if_mixed();
diff --git a/sql/sql_error.h b/sql/sql_error.h
index 70d40e3..aa8e6c6b 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -712,7 +712,10 @@ class Diagnostics_area
                 m_status == DA_OK_BULK); return m_message; }
 
   bool skip_flush() const
-  { DBUG_ASSERT(m_status == DA_OK); return m_skip_flush; }
+  {
+    DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
+    return m_skip_flush;
+  }
 
   void set_skip_flush()
   { m_skip_flush= TRUE; }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 7dcade9..d2ec008 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -638,6 +638,66 @@ static void save_insert_query_plan(THD* thd, TABLE_LIST *table_list)
 }
 
 
+inline static void set_defaults_relation(Item *fld, Item *val)
+{
+  Item::Type type= fld->type();
+  if (type == Item::FIELD_ITEM)
+  {
+    Item_field *item_field= (Item_field *)fld;
+    if (item_field->fixed)
+      val->set_default_value_source(item_field->field);
+    else
+      item_field->set_default_value_target(val);
+  }
+  else if (type == Item::REF_ITEM)
+  {
+    Item_ref *item_field= (Item_ref *)fld;
+    // may turn to Item_field after fix_fields()
+    if (!item_field->fixed)
+      item_field->set_default_value_target(val);
+  }
+}
+
+void setup_deault_parameters(TABLE_LIST *table, List<Item> *fields,
+                             List<Item> *values)
+{
+
+  List_iterator_fast<Item> itv(*values);
+  Item *val;
+  if (fields->elements)
+  {
+    List_iterator_fast<Item> itf(*fields);
+    Item *fld;
+    while((fld= itf++) && (val= itv++))
+    {
+      set_defaults_relation(fld->real_item(), val);
+    }
+  }
+  else if (table != NULL)
+  {
+    if (table->view)
+    {
+      Field_iterator_view field_it;
+      field_it.set(table);
+      for (; !field_it.end_of_fields() && (val= itv++); field_it.next())
+      {
+        set_defaults_relation(field_it.item()->real_item(), val);
+      }
+    }
+    else
+    {
+      Field_iterator_table_ref field_it;
+      field_it.set(table);
+      for (; !field_it.end_of_fields() && (val= itv++); field_it.next())
+      {
+        Field *fld= field_it.field();
+        val->set_default_value_source(fld);
+      }
+    }
+  }
+}
+
+
 /**
   INSERT statement implementation
 
@@ -727,11 +787,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
   THD_STAGE_INFO(thd, stage_init);
   thd->lex->used_tables=0;
   values= its++;
-  DBUG_ASSERT(bulk_iterations > 0);
-  if (bulk_parameters_set(thd))
-    DBUG_RETURN(TRUE);
   value_count= values->elements;
 
+  DBUG_ASSERT(bulk_iterations > 0);
   if (mysql_prepare_insert(thd, table_list, table, fields, values,
 			   update_fields, update_values, duplic, &unused_conds,
                            FALSE,
@@ -775,6 +833,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
     if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0))
       goto abort;
     switch_to_nullable_trigger_fields(*values, table);
+    setup_deault_parameters(table_list, &fields, values);
   }
   its.rewind ();
  
@@ -1458,6 +1517,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
   /* Prepare the fields in the statement. */
   if (values)
   {
+
     /* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
     DBUG_ASSERT (!select_lex->group_list.elements);
 
@@ -1476,6 +1536,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
           check_insert_fields(thd, context->table_list, fields, *values,
                               !insert_into_view, 0, &map));
 
+    setup_deault_parameters(table_list, &fields, values);
+    if (bulk_parameters_set(thd))
+      DBUG_RETURN(TRUE);
+
     if (!res && check_fields)
     {
       bool saved_abort_on_warning= thd->abort_on_warning;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 44e4380..e421b1d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -391,7 +391,7 @@ const LEX_STRING command_name[257]={
   { 0, 0 }, //247
   { 0, 0 }, //248
   { 0, 0 }, //249
-  { C_STRING_WITH_LEN("Execute_bulk") }, //250
+  { 0, 0 }, //250
   { C_STRING_WITH_LEN("Slave_worker") }, //251
   { C_STRING_WITH_LEN("Slave_IO") }, //252
   { C_STRING_WITH_LEN("Slave_SQL") }, //253
@@ -1746,12 +1746,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
   }
   case COM_STMT_EXECUTE:
   {
-    mysqld_stmt_execute(thd, packet, packet_length);
-    break;
-  }
-  case COM_STMT_BULK_EXECUTE:
-  {
-    mysqld_stmt_bulk_execute(thd, packet, packet_length);
+    ulong iterations= uint4korr(packet + 5);
+    if (iterations < 2  ||
+        (thd->client_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS))
+      mysqld_stmt_execute(thd, packet, packet_length);
+    else
+      mysqld_stmt_bulk_execute(thd, packet, packet_length);
     break;
   }
   case COM_STMT_FETCH:
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4b0f9df..81ef548 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -188,7 +188,7 @@ class Prepared_statement: public Statement
   bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
                      uchar *read_pos, String *expanded_query);
   bool (*set_bulk_params)(Prepared_statement *st,
-                          uchar **read_pos, uchar *data_end);
+                          uchar **read_pos, uchar *data_end, bool reset);
 #else
   bool (*set_params_data)(Prepared_statement *st, String *expanded_query);
   /*TODO: add bulk support for builtin server */
@@ -216,7 +216,7 @@ class Prepared_statement: public Statement
                          uchar *packet_arg, uchar *packet_end_arg,
                          ulong iterations);
   bool execute_server_runnable(Server_runnable *server_runnable);
-  my_bool set_bulk_parameters();
+  my_bool set_bulk_parameters(bool reset);
   ulong bulk_iterations();
   /* Destroy this statement */
   void deallocate();
@@ -974,7 +974,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
 
 
 static bool insert_bulk_params(Prepared_statement *stmt,
-                               uchar **read_pos, uchar *data_end)
+                               uchar **read_pos, uchar *data_end,
+                               bool reset)
 {
   Item_param **begin= stmt->param_array;
   Item_param **end= begin + stmt->param_count;
@@ -984,16 +985,17 @@ static bool insert_bulk_params(Prepared_statement *stmt,
   for (Item_param **it= begin; it < end; ++it)
   {
     Item_param *param= *it;
+    if (reset)
+      param->reset();
     if (param->state != Item_param::LONG_DATA_VALUE)
     {
-      uint indicators;
       if (param->indicators)
-        indicators= *((*read_pos)++);
+        param->indicator= *((*read_pos)++);
       else
-        indicators= STMT_INDICATOR_NONE;
-      if ((*read_pos) >= data_end)
+        param->indicator= STMT_INDICATOR_NONE;
+      if ((*read_pos) > data_end)
         DBUG_RETURN(1);
-      switch (indicators) {
+      switch (param->indicator) {
       case STMT_INDICATOR_NONE:
         if ((*read_pos) >= data_end)
           DBUG_RETURN(1);
@@ -1005,8 +1007,8 @@ static bool insert_bulk_params(Prepared_statement *stmt,
         param->set_null();
         break;
       case STMT_INDICATOR_DEFAULT:
-        // TODO: support default
-        DBUG_ASSERT(0);
+        if (param->set_default(TRUE))
+          DBUG_RETURN(1);
         break;
       }
     }
@@ -3573,7 +3575,8 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
   iterations(0),
   param_count(0),
   last_errno(0),
-  flags((uint) IS_IN_USE)
+  flags((uint) IS_IN_USE),
+  start_param(0)
 {
   init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size,
                  thd_arg->variables.query_prealloc_size, MYF(MY_THREAD_SPECIFIC));
@@ -3990,6 +3993,7 @@ Prepared_statement::execute_loop(String *expanded_query,
   Reprepare_observer reprepare_observer;
   bool error;
   int reprepare_attempt= 0;
+  iterations= 0;
 #ifndef DBUG_OFF
   Item *free_list_state= thd->free_list;
 #endif
@@ -4083,11 +4087,12 @@ Prepared_statement::execute_loop(String *expanded_query,
 
 my_bool bulk_parameters_set(THD *thd)
 {
+  DBUG_ENTER("bulk_parameters_set");
   Prepared_statement *stmt= (Prepared_statement *) thd->bulk_param;
 
-  if (stmt && stmt->set_bulk_parameters())
-    return FALSE;
-  return FALSE;
+  if (stmt && stmt->set_bulk_parameters(FALSE))
+    DBUG_RETURN(TRUE);
+  DBUG_RETURN(FALSE);
 }
 
 ulong bulk_parameters_iterations(THD *thd)
@@ -4099,12 +4104,14 @@ ulong bulk_parameters_iterations(THD *thd)
 }
 
 
-my_bool Prepared_statement::set_bulk_parameters()
+my_bool Prepared_statement::set_bulk_parameters(bool reset)
 {
+  DBUG_ENTER("Prepared_statement::set_bulk_parameters");
+  DBUG_PRINT("info", ("iteration: %lu", iterations));
   if (iterations)
   {
 #ifndef EMBEDDED_LIBRARY
-    if ((*set_bulk_params)(this, &packet, packet_end))
+    if ((*set_bulk_params)(this, &packet, packet_end, reset))
 #else
       DBUG_ASSERT(0); //TODO: support bulk parameters for embedded server
 #endif
@@ -4112,12 +4119,12 @@ my_bool Prepared_statement::set_bulk_parameters()
       my_error(ER_WRONG_ARGUMENTS, MYF(0),
                "mysqld_stmt_bulk_execute");
       reset_stmt_params(this);
-      return true;
+      DBUG_RETURN(true);
     }
     iterations--;
   }
   start_param= 0;
-  return false;
+  DBUG_RETURN(false);
 }
 
 ulong Prepared_statement::bulk_iterations()
@@ -4174,7 +4181,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
   }
 
 #ifdef NOT_YET_FROM_MYSQL_5_6
-  if (unlikely(thd->security_ctx->password_expired && 
+  if (unlikely(thd->security_ctx->password_expired &&
                !lex->is_change_password))
   {
     my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
@@ -4189,7 +4196,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
 
     if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_OPTIMIZED))
     {
-      if (set_bulk_parameters())
+      if (set_bulk_parameters(TRUE))
       {
         thd->set_bulk_execution(0);
         return true;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b452e4f..ecd32e2 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -221,6 +221,8 @@ static void prepare_record_for_error_message(int error, TABLE *table)
   DBUG_VOID_RETURN;
 }
 
+void setup_deault_parameters(TABLE_LIST *table, List<Item> *fields,
+                             List<Item> *values);
 
 /*
   Process usual UPDATE
@@ -354,6 +356,8 @@ int mysql_update(THD *thd,
     DBUG_RETURN(1);
   }
 
+  setup_deault_parameters(NULL, &fields, &values);
+
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   /* Check values */
   table_list->grant.want_privilege= table->grant.want_privilege=


More information about the commits mailing list