diff -Narup ./005_mariadb-10.0.15-hs/sql/handler.cc ./006_mariadb-10.0.15-direct_update_rows/sql/handler.cc
--- ./005_mariadb-10.0.15-hs/sql/handler.cc	2014-11-22 06:02:53.000000000 +0900
+++ ./006_mariadb-10.0.15-direct_update_rows/sql/handler.cc	2014-11-29 17:02:06.101796936 +0900
@@ -6022,6 +6022,102 @@ int handler::ha_delete_row(const uchar *
   return 0;
 }
 
+int handler::ha_direct_update_rows_init(
+  uint mode,
+  KEY_MULTI_RANGE *ranges,
+  uint range_count,
+  bool sorted,
+  uchar *new_data
+) {
+  int error;
+  /*
+    Some storage engines require that the new record is in record[0]
+    (and the old record is in record[1]).
+   */
+  DBUG_ASSERT(new_data == table->record[0]);
+
+  error=
+    direct_update_rows_init(mode, ranges, range_count, sorted, new_data);
+  return error;
+}
+
+int handler::ha_direct_update_rows(
+  KEY_MULTI_RANGE *ranges,
+  uint range_count,
+  bool sorted,
+  uchar *new_data,
+  uint *update_rows
+) {
+  int error;
+  /*
+    Some storage engines require that the new record is in record[0]
+    (and the old record is in record[1]).
+   */
+  DBUG_ASSERT(new_data == table->record[0]);
+
+  MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
+  mark_trx_read_write();
+
+  error=
+    direct_update_rows(ranges, range_count, sorted, new_data, update_rows);
+  MYSQL_UPDATE_ROW_DONE(error);
+  return error;
+}
+
+int handler::ha_direct_update_row_binlog(
+  const uchar *old_data,
+  uchar *new_data
+) {
+  int error;
+  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
+
+  /*
+    Some storage engines require that the new record is in record[0]
+    (and the old record is in record[1]).
+   */
+  DBUG_ASSERT(new_data == table->record[0]);
+
+  error= binlog_log_row(table, old_data, new_data, log_func);
+  return error;
+}
+
+int handler::ha_direct_delete_rows_init(
+  uint mode,
+  KEY_MULTI_RANGE *ranges,
+  uint range_count,
+  bool sorted
+) {
+  int error;
+  error=
+    direct_delete_rows_init(mode, ranges, range_count, sorted);
+  return error;
+}
+
+int handler::ha_direct_delete_rows(
+  KEY_MULTI_RANGE *ranges,
+  uint range_count,
+  bool sorted,
+  uint *delete_rows
+) {
+  int error;
+  MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
+  mark_trx_read_write();
+
+  error=
+    direct_delete_rows(ranges, range_count, sorted, delete_rows);
+  MYSQL_DELETE_ROW_DONE(error);
+  return error;
+}
+
+int handler::ha_direct_delete_row_binlog(const uchar *buf)
+{
+  int error;
+  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
+
+  error= binlog_log_row(table, buf, 0, log_func);
+  return 0;
+}
+
 
 
 /** @brief
diff -Narup ./005_mariadb-10.0.15-hs/sql/handler.h ./006_mariadb-10.0.15-direct_update_rows/sql/handler.h
--- ./005_mariadb-10.0.15-hs/sql/handler.h	2014-11-29 17:01:25.378795153 +0900
+++ ./006_mariadb-10.0.15-direct_update_rows/sql/handler.h	2014-11-29 17:02:06.103395102 +0900
@@ -40,6 +40,7 @@
 #include <mysql/psi/mysql_table.h>
 
 #define HANDLER_HAS_TOP_TABLE_FIELDS
+#define HANDLER_HAS_DIRECT_UPDATE_ROWS
 
 #if MAX_KEY > 128
 #error MAX_KEY is too large.  Values up to 128 are supported.
@@ -2666,6 +2667,39 @@ public:
   int ha_write_row(uchar * buf);
   int ha_update_row(const uchar * old_data, uchar * new_data);
   int ha_delete_row(const uchar * buf);
+  int ha_direct_update_rows_init(
+    uint mode,
+    KEY_MULTI_RANGE *ranges,
+    uint range_count,
+    bool sorted,
+    uchar *new_data
+  );
+  int ha_direct_update_rows(
+    KEY_MULTI_RANGE *ranges,
+    uint range_count,
+    bool sorted,
+    uchar *new_data,
+    uint *update_rows
+  );
+  int ha_direct_update_row_binlog(
+    const uchar *old_data,
+    uchar *new_data
+  );
+  int ha_direct_delete_rows_init(
+    uint mode,
+    KEY_MULTI_RANGE *ranges,
+    uint range_count,
+    bool sorted
+  );
+  int ha_direct_delete_rows(
+    KEY_MULTI_RANGE *ranges,
+    uint range_count,
+    bool sorted,
+    uint *delete_rows
+  );
+  int ha_direct_delete_row_binlog(
+    const uchar *buf
+  );
   void ha_release_auto_increment();
 
   int check_collation_compatibility();
@@ -3384,6 +3418,7 @@ public:
    Pops the top if condition stack, if stack is not empty.
  */
  virtual void cond_pop() { return; };
+ virtual int info_push(uint info_type, void *info) { return 0; };
  virtual int set_top_table_and_fields(TABLE *top_table,
                                       Field **top_table_field,
                                       uint top_table_fields)
@@ -3815,6 +3850,45 @@ private:
   {
     return HA_ERR_WRONG_COMMAND;
   }
+
+  virtual int direct_update_rows_init(
+    uint mode __attribute__((unused)),
+    KEY_MULTI_RANGE *ranges __attribute__((unused)),
+    uint range_count __attribute__((unused)),
+    bool sorted __attribute__((unused)),
+    uchar *new_data __attribute__((unused)))
+  {
+    return HA_ERR_WRONG_COMMAND;
+  }
+
+  virtual int direct_update_rows(
+    KEY_MULTI_RANGE *ranges __attribute__((unused)),
+    uint range_count __attribute__((unused)),
+    bool sorted __attribute__((unused)),
+    uchar *new_data __attribute__((unused)),
+    uint *update_rows __attribute__((unused)))
+  {
+    return HA_ERR_WRONG_COMMAND;
+  }
+
+  virtual int direct_delete_rows_init(
+    uint mode __attribute__((unused)),
+    KEY_MULTI_RANGE *ranges __attribute__((unused)),
+    uint range_count __attribute__((unused)),
+    bool sorted __attribute__((unused)))
+  {
+    return HA_ERR_WRONG_COMMAND;
+  }
+
+  virtual int direct_delete_rows(
+    KEY_MULTI_RANGE *ranges __attribute__((unused)),
+    uint range_count __attribute__((unused)),
+    bool sorted __attribute__((unused)),
+    uint *delete_rows __attribute__((unused)))
+  {
+    return HA_ERR_WRONG_COMMAND;
+  }
+
   /**
     Reset state of file to after 'open'.
     This function is called after every statement for all tables used
