[Groonga-mysql-commit] mroonga/mroonga [master] Support create/drop index for storage mode

Back to archive index

null+****@clear***** null+****@clear*****
2011年 10月 24日 (月) 12:31:19 JST


Kentoku	2011-10-24 03:31:19 +0000 (Mon, 24 Oct 2011)

  New Revision: abe2654bca288fd81b08075acdea510961e441c2

  Log:
    Support create/drop index for storage mode

  Modified files:
    ha_mroonga.cc
    ha_mroonga.h

  Modified: ha_mroonga.cc (+226 -95)
===================================================================
--- ha_mroonga.cc    2011-10-23 07:33:19 +0000 (cb27c12)
+++ ha_mroonga.cc    2011-10-24 03:31:19 +0000 (dbf6245)
@@ -927,6 +927,23 @@ static void mrn_store_field(grn_ctx *ctx, Field *field, grn_obj *col, grn_id id)
   grn_obj_unlink(ctx, &buf);
 }
 
+static uint mrn_alter_table_flags(uint flags) {
+  uint ret_flags =
+    HA_INPLACE_ADD_INDEX_NO_READ_WRITE |
+    HA_INPLACE_DROP_INDEX_NO_READ_WRITE |
+    HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE |
+    HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE |
+    HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE |
+    HA_INPLACE_DROP_PK_INDEX_NO_READ_WRITE |
+    HA_INPLACE_ADD_INDEX_NO_WRITE |
+    HA_INPLACE_DROP_INDEX_NO_WRITE |
+    HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE |
+    HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE |
+    HA_INPLACE_ADD_PK_INDEX_NO_WRITE |
+    HA_INPLACE_DROP_PK_INDEX_NO_WRITE;
+  return ret_flags;
+}
+
 static int mrn_init(void *p)
 {
   // init handlerton
@@ -939,6 +956,7 @@ static int mrn_init(void *p)
   hton->drop_database = mrn_drop_db;
   hton->close_connection = mrn_close_connection;
   hton->flush_logs = mrn_flush_logs;
+  hton->alter_table_flags = mrn_alter_table_flags;
   mrn_hton_ptr = hton;
 
   // init groonga
@@ -1777,7 +1795,7 @@ int ha_mroonga::storage_create(const char *name, TABLE *table,
     }
   }
 
-  error = storage_create_index(table, tbl_name, tbl_obj, tmp_share);
+  error = storage_create_indexs(table, tbl_name, tbl_obj, tmp_share);
   if (error) {
     grn_obj_remove(ctx, tbl_obj);
     tbl_obj = NULL;
@@ -1865,102 +1883,123 @@ int ha_mroonga::storage_create_validate_index(TABLE *table)
 }
 
 int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name,
-                                     grn_obj *grn_table, MRN_SHARE *tmp_share)
+                                     grn_obj *grn_table, MRN_SHARE *tmp_share,
+                                     KEY *key_info, grn_obj **index_tables,
+                                     uint i)
 {
   MRN_DBUG_ENTER_METHOD();
   int error = 0;
-
   char index_table_name[MRN_MAX_KEY_SIZE];
+  grn_obj *index_table, *index_column;
+  grn_obj *column = NULL;
+  grn_obj *index_type = NULL;
 
-  uint n_keys = table->s->keys;
-  for (int i = 0; i < n_keys; i++) {
-    if (i == table->s->primary_key) {
-      continue; // pkey is already handled
-    }
+  mrn_index_table_name_gen(grn_table_name, key_info->name, index_table_name);
 
-    grn_obj *index_table, *index_column;
-    grn_obj *column = NULL;
-    grn_obj *index_type = NULL;
-    KEY key_info = table->s->key_info[i];
+  int key_parts = key_info->key_parts;
+  grn_obj_flags index_table_flags = GRN_OBJ_PERSISTENT;
+  if (key_parts == 1) {
+    Field *field = key_info->key_part[0].field;
+    const char *column_name = field->field_name;
+    int column_name_size = strlen(column_name);
 
-    mrn_index_table_name_gen(grn_table_name, key_info.name, index_table_name);
+    if (strncmp(MRN_COLUMN_NAME_ID, column_name, column_name_size) == 0) {
+      // skipping _id virtual column
+      DBUG_RETURN(0);
+    }
 
-    int key_parts = key_info.key_parts;
-    grn_obj_flags index_table_flags = GRN_OBJ_PERSISTENT;
-    if (key_parts == 1) {
-      Field *field = key_info.key_part[0].field;
-      const char *column_name = field->field_name;
-      int column_name_size = strlen(column_name);
+    column = grn_obj_column(ctx, grn_table, column_name, column_name_size);
+    int mysql_field_type = field->type();
+    grn_builtin_type groonga_type = mrn_get_type(ctx, mysql_field_type);
+    index_type = grn_ctx_at(ctx, groonga_type);
+    index_table_flags |= GRN_OBJ_KEY_NORMALIZE;
+  } else {
+    index_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
+  }
 
-      if (strncmp(MRN_COLUMN_NAME_ID, column_name, column_name_size) == 0) {
-        // skipping _id virtual column
-        continue;
-      }
+  int key_alg = key_info->algorithm;
+  if (key_alg == HA_KEY_ALG_FULLTEXT) {
+    index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
+  } else if (key_alg == HA_KEY_ALG_HASH) {
+    index_table_flags |= GRN_OBJ_TABLE_HASH_KEY;
+  } else {
+    index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
+  }
 
-      column = grn_obj_column(ctx, grn_table, column_name, column_name_size);
-      int mysql_field_type = field->type();
-      grn_builtin_type groonga_type = mrn_get_type(ctx, mysql_field_type);
-      index_type = grn_ctx_at(ctx, groonga_type);
-      index_table_flags |= GRN_OBJ_KEY_NORMALIZE;
-    } else {
-      index_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
-    }
+  index_table = grn_table_create(ctx,
+                                 index_table_name,
+                                 strlen(index_table_name),
+                                 NULL,
+                                 index_table_flags,
+                                 index_type,
+                                 0);
+  if (ctx->rc) {
+    grn_obj_remove(ctx, grn_table);
+    error = ER_CANT_CREATE_TABLE;
+    my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0));
+    DBUG_RETURN(error);
+  }
 
-    int key_alg = key_info.algorithm;
-    if (key_alg == HA_KEY_ALG_FULLTEXT) {
-      index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
-    } else if (key_alg == HA_KEY_ALG_HASH) {
-      index_table_flags |= GRN_OBJ_TABLE_HASH_KEY;
-    } else {
-      index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
-    }
+  if (key_alg == HA_KEY_ALG_FULLTEXT) {
+    grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER;
+    grn_obj *tokenizer = find_tokenizer(tmp_share->key_parser[i],
+                                        tmp_share->key_parser_length[i]);
+    grn_obj_set_info(ctx, index_table, info_type, tokenizer);
+    grn_obj_unlink(ctx, tokenizer);
+  }
 
-    index_table = grn_table_create(ctx,
-                                   index_table_name,
-                                   strlen(index_table_name),
-                                   NULL,
-                                   index_table_flags,
-                                   index_type,
-                                   0);
-    if (ctx->rc) {
-      grn_obj_remove(ctx, grn_table);
-      error = ER_CANT_CREATE_TABLE;
-      my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0));
-      DBUG_RETURN(error);
-    }
+  grn_obj_flags index_column_flags =
+    GRN_OBJ_COLUMN_INDEX | GRN_OBJ_WITH_POSITION | GRN_OBJ_PERSISTENT;
+  index_column = grn_column_create(ctx,
+                                  index_table,
+                                  index_column_name,
+                                  strlen(index_column_name),
+                                  NULL,
+                                  index_column_flags,
+                                  grn_table);
 
-    if (key_alg == HA_KEY_ALG_FULLTEXT) {
-      grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER;
-      grn_obj *tokenizer = find_tokenizer(tmp_share->key_parser[i],
-                                          tmp_share->key_parser_length[i]);
-      grn_obj_set_info(ctx, index_table, info_type, tokenizer);
-      grn_obj_unlink(ctx, tokenizer);
-    }
+  if (ctx->rc) {
+    grn_obj_remove(ctx, index_table);
+    error = ER_CANT_CREATE_TABLE;
+    my_message(error, ctx->errbuf, MYF(0));
+    DBUG_RETURN(error);
+  }
 
-    grn_obj_flags index_column_flags =
-      GRN_OBJ_COLUMN_INDEX | GRN_OBJ_WITH_POSITION | GRN_OBJ_PERSISTENT;
-    index_column = grn_column_create(ctx,
-                                    index_table,
-                                    index_column_name,
-                                    strlen(index_column_name),
-                                    NULL,
-                                    index_column_flags,
-                                    grn_table);
+  if (column) {
+    grn_obj source_ids;
+    grn_id source_id = grn_obj_id(ctx, column);
+    GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
+    GRN_UINT32_PUT(ctx, &source_ids, source_id);
+    grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids);
+    grn_obj_unlink(ctx, &source_ids);
+  }
+  index_tables[i] = index_table;
+  DBUG_RETURN(error);
+}
 
-    if (ctx->rc) {
-      grn_obj_remove(ctx, index_table);
-      error = ER_CANT_CREATE_TABLE;
-      my_message(error, ctx->errbuf, MYF(0));
-      DBUG_RETURN(error);
-    }
+int ha_mroonga::storage_create_indexs(TABLE *table, const char *grn_table_name,
+                                      grn_obj *grn_table, MRN_SHARE *tmp_share)
+{
+  MRN_DBUG_ENTER_METHOD();
+  int error = 0, i;
 
-    if (column) {
-      grn_obj source_ids;
-      grn_id source_id = grn_obj_id(ctx, column);
-      GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
-      GRN_UINT32_PUT(ctx, &source_ids, source_id);
-      grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids);
-      grn_obj_unlink(ctx, &source_ids);
+  uint n_keys = table->s->keys;
+  grn_obj *index_tables[n_keys];
+  for (i = 0; i < n_keys; i++) {
+    index_tables[i] = NULL;
+    if (i == table->s->primary_key) {
+      continue; // pkey is already handled
+    }
+    if ((error = storage_create_index(table, grn_table_name, grn_table,
+                                      tmp_share, &table->s->key_info[i],
+                                      index_tables, i)))
+      DBUG_RETURN(error);
+  }
+  if (error) {
+    for (; i >= 0; i--) {
+      if (index_tables[i]) {
+        grn_obj_remove(ctx, index_tables[i]);
+      }
     }
   }
 
@@ -2085,6 +2124,14 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info)
   int i, error = 0;
   MRN_SHARE *tmp_share;
   MRN_DBUG_ENTER_METHOD();
+  uint sql_command = thd_sql_command(ha_thd());
+  if (
+    sql_command == SQLCOM_CREATE_INDEX ||
+    sql_command == SQLCOM_DROP_INDEX ||
+    sql_command == SQLCOM_ALTER_TABLE
+  )
+    DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+
   /* checking data type of virtual columns */
 
   if (!(tmp_share = mrn_get_share(name, table, &error)))
@@ -2677,6 +2724,13 @@ int ha_mroonga::delete_table(const char *name)
   TABLE tmp_table;
   MRN_SHARE *tmp_share;
   MRN_DBUG_ENTER_METHOD();
+  uint sql_command = thd_sql_command(ha_thd());
+  if (
+    sql_command == SQLCOM_CREATE_INDEX ||
+    sql_command == SQLCOM_DROP_INDEX ||
+    sql_command == SQLCOM_ALTER_TABLE
+  )
+    DBUG_RETURN(HA_ERR_WRONG_COMMAND);
   mrn_db_name_gen(name, db_name);
   mrn_table_name_gen(name, tbl_name);
 #if MYSQL_VERSION_ID >= 50500
@@ -6623,6 +6677,8 @@ int ha_mroonga::rename_table(const char *from, const char *to)
 {
   MRN_DBUG_ENTER_METHOD();
   int error = 0;
+  if (!share)
+    DBUG_RETURN(HA_ERR_WRONG_COMMAND);
   if (share->wrapper_mode)
   {
     error = wrapper_rename_table(from, to);
@@ -7057,7 +7113,7 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
   bitmap_clear_all(table->read_set);
   mrn_set_bitmap_by_key(table->read_set, p_key_info);
   for (i = 0, j = 0; i < num_of_keys; i++) {
-    if (!(key_info[i].flags & HA_FULLTEXT)) {
+    if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) {
       wrap_key_info[j] = key_info[i];
       j++;
       continue;
@@ -7067,11 +7123,20 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
       break;
     }
     index_tables[i + n_keys] = NULL;
-    if ((res = wrapper_create_index_fulltext(grn_table, grn_table_name,
-                                             i + n_keys,
-                                             &key_info[i], index_tables,
-                                             tmp_share)))
-    {
+    if (
+      (key_info[i].flags & HA_FULLTEXT) &&
+      (res = wrapper_create_index_fulltext(grn_table, grn_table_name,
+                                           i + n_keys,
+                                           &key_info[i], index_tables,
+                                           tmp_share))
+    ) {
+      break;
+    } else if (
+      mrn_is_geo_key(&key_info[i]) &&
+      (res = wrapper_create_index_geo(grn_table, grn_table_name,
+                                      i + n_keys, &key_info[i],
+                                      index_tables, tmp_share))
+    ) {
       break;
     }
     mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
@@ -7178,10 +7243,62 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
 }
 
 int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
-  uint num_of_keys, handler_add_index **add)
+                                  uint num_of_keys, handler_add_index **add)
 {
+  int res = 0;
+  uint i, j, k;
+  uint n_keys = table->s->keys;
+  grn_obj *index_tables[num_of_keys + n_keys];
+  char grn_table_name[MRN_MAX_PATH_SIZE];
+  THD *thd = ha_thd();
+  MRN_SHARE *tmp_share;
+  TABLE_SHARE tmp_table_share;
+  char **key_parser;
+  uint *key_parser_length;
   MRN_DBUG_ENTER_METHOD();
-  int res = handler::add_index(table_arg, key_info, num_of_keys, add);
+  KEY *wrap_key_info = (KEY *) thd->alloc(sizeof(KEY) * num_of_keys);
+  KEY *p_key_info = &table->key_info[table_share->primary_key], *tmp_key_info;
+  tmp_table_share.keys = n_keys + num_of_keys;
+  if (!(tmp_share = (MRN_SHARE *)
+    my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+      &tmp_share, sizeof(*tmp_share),
+      &key_parser, sizeof(char *) * (n_keys + num_of_keys),
+      &key_parser_length, sizeof(uint) * (n_keys + num_of_keys),
+      NullS))
+  ) {
+    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+  }
+  tmp_share->engine = NULL;
+  tmp_share->table_share = &tmp_table_share;
+  tmp_share->key_parser = key_parser;
+  tmp_share->key_parser_length = key_parser_length;
+  mrn_table_name_gen(share->table_name, grn_table_name);
+  for (i = 0; i < num_of_keys; i++) {
+    index_tables[i + n_keys] = NULL;
+    if ((res = mrn_add_index_param(tmp_share, &key_info[i], i + n_keys)))
+    {
+      break;
+    }
+    if ((res = storage_create_index(table, grn_table_name, grn_table,
+                                    tmp_share, &key_info[i], index_tables,
+                                    i + n_keys)))
+    {
+      break;
+    }
+  }
+  if (res)
+  {
+    for (k = 0; k < i; k++) {
+      if (index_tables[k + n_keys])
+      {
+        grn_obj_remove(ctx, index_tables[k + n_keys]);
+      }
+    }
+  } else {
+    *add = new handler_add_index(table_arg, key_info, num_of_keys);
+  }
+  mrn_free_share_alloc(tmp_share);
+  my_free(tmp_share, MYF(0));
   DBUG_RETURN(res);
 }
 
@@ -7221,8 +7338,11 @@ int ha_mroonga::wrapper_final_add_index(handler_add_index *add, bool commit)
 int ha_mroonga::storage_final_add_index(handler_add_index *add, bool commit)
 {
   MRN_DBUG_ENTER_METHOD();
-  int res = handler::final_add_index(add, commit);
-  DBUG_RETURN(res);
+  if (add)
+  {
+    delete add;
+  }
+  DBUG_RETURN(0);
 }
 
 int ha_mroonga::final_add_index(handler_add_index *add, bool commit)
@@ -7276,9 +7396,21 @@ int ha_mroonga::wrapper_prepare_drop_index(TABLE *table_arg, uint *key_num,
 int ha_mroonga::storage_prepare_drop_index(TABLE *table_arg, uint *key_num,
   uint num_of_keys)
 {
+  uint i;
+  KEY *key_info = table_share->key_info;
+  char grn_table_name[MRN_MAX_PATH_SIZE];
   MRN_DBUG_ENTER_METHOD();
-  int res = handler::prepare_drop_index(table_arg, key_num, num_of_keys);
-  DBUG_RETURN(res);
+  mrn_table_name_gen(share->table_name, grn_table_name);
+  for (i = 0; i < num_of_keys; i++) {
+    char index_name[MRN_MAX_PATH_SIZE];
+    mrn_index_table_name_gen(grn_table_name, key_info[key_num[i]].name,
+                             index_name);
+    grn_obj *index_table = grn_ctx_get(ctx, index_name, strlen(index_name));
+    if (index_table != NULL) {
+      grn_obj_remove(ctx, index_table);
+    }
+  }
+  DBUG_RETURN(0);
 }
 
 int ha_mroonga::prepare_drop_index(TABLE *table_arg, uint *key_num,
@@ -7310,8 +7442,7 @@ int ha_mroonga::wrapper_final_drop_index(TABLE *table_arg)
 int ha_mroonga::storage_final_drop_index(TABLE *table_arg)
 {
   MRN_DBUG_ENTER_METHOD();
-  uint res = handler::final_drop_index(table_arg);
-  DBUG_RETURN(res);
+  DBUG_RETURN(0);
 }
 
 int ha_mroonga::final_drop_index(TABLE *table_arg)

  Modified: ha_mroonga.h (+3 -0)
===================================================================
--- ha_mroonga.h    2011-10-23 07:33:19 +0000 (4f0adb6)
+++ ha_mroonga.h    2011-10-24 03:31:19 +0000 (53c3d5f)
@@ -362,6 +362,9 @@ private:
   int storage_create_validate_pseudo_column(TABLE *table);
   int storage_create_validate_index(TABLE *table);
   int storage_create_index(TABLE *table, const char *grn_table_name,
+                           grn_obj *grn_table, MRN_SHARE *tmp_share,
+                           KEY *key_info, grn_obj **index_tables, uint i);
+  int storage_create_indexs(TABLE *table, const char *grn_table_name,
                            grn_obj *grn_table, MRN_SHARE *tmp_share);
   int close_databases();
   int ensure_database_create(const char *name);




Groonga-mysql-commit メーリングリストの案内
Back to archive index