null+****@clear*****
null+****@clear*****
2011年 6月 6日 (月) 18:55:34 JST
Kentoku 2011-06-06 09:55:34 +0000 (Mon, 06 Jun 2011) New Revision: 7889e0344f9f3386a04495012de608e19b57e246 Log: Add wrapper "create table" and "drop table" prototype. Added files: mrn_err.h mrn_table.cc mrn_table.h Modified files: Makefile.am ha_mroonga.cc ha_mroonga.h Modified: Makefile.am (+3 -3) =================================================================== --- Makefile.am 2011-05-29 13:12:18 +0000 (fb8d4e2) +++ Makefile.am 2011-06-06 09:55:34 +0000 (528f505) @@ -3,19 +3,19 @@ AUTOMAKE_OPTIONS = 1.9.7 AM_CPPFLAGS = $(MYSQL_INC) $(GROONGA_CFLAGS) $(MECAB_INCLUDES) $(MYSQL_VERSION_CFLAGS) ACLOCAL_AMFLAGS = $$ACLOCAL_ARGS -noinst_HEADERS = mrnsys.h ha_mroonga.h +noinst_HEADERS = mrnsys.h ha_mroonga.h mrn_table.h mrn_err.h plugin_LTLIBRARIES = ha_groonga.la ha_groonga_la_LDFLAGS = -module $(GROONGA_LIBS) $(MECAB_LIBS) ha_groonga_la_CXXFLAGS = $(AM_CFLAGS) $(MYSQL_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN ha_groonga_la_CFLAGS = $(AM_CFLAGS) $(MYSQL_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -ha_groonga_la_SOURCES = ha_mroonga.cc mrnsys.c +ha_groonga_la_SOURCES = ha_mroonga.cc mrnsys.c mrn_table.cc plugin_LIBRARIES = libgroonga_storage_engine.a libgroonga_storage_engine_a_LDFLANGS = $(GROONGA_LIBS) $(MECAB_LIBS) libgroonga_storage_engine_a_CXXFLAGS = $(AM_CFLAGS) $(MYSQL_CFLAGS) libgroonga_storage_engine_a_CFLAGS = $(AM_CFLAGS) $(MYSQL_CFLAGS) -libgroonga_storage_engine_a_SOURCES = ha_mroonga.cc mrnsys.c +libgroonga_storage_engine_a_SOURCES = ha_mroonga.cc mrnsys.c mrn_table.cc SUBDIRS = test apt rpm yum doc Modified: ha_mroonga.cc (+217 -44) =================================================================== --- ha_mroonga.cc 2011-05-29 13:12:18 +0000 (2aacbdc) +++ ha_mroonga.cc 2011-06-06 09:55:34 +0000 (93e924e) @@ -36,6 +36,7 @@ #endif #define MYSQL_SERVER 1 +#include "mysql_version.h" #ifdef MYSQL51 #include <mysql_priv.h> @@ -46,6 +47,7 @@ #include <probes_mysql.h> #include <sql_plugin.h> #include <sql_show.h> +#include "sql_partition.h" #endif #include <sql_select.h> #include <ft_global.h> @@ -54,12 +56,20 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include "mrn_err.h" +#include "mrn_table.h" #include "ha_mroonga.h" #ifdef __cplusplus extern "C" { #endif +#if MYSQL_VERSION_ID >= 50500 +extern mysql_mutex_t LOCK_open; +#else +extern pthread_mutex_t LOCK_open; +#endif + /* global variables */ grn_obj *mrn_db; grn_hash *mrn_hash; @@ -73,6 +83,17 @@ _ft_vft mrn_ft_vft = { NULL // mrn_ft_reinit_search }; handlerton *mrn_hton_ptr; +HASH mrn_open_tables; +pthread_mutex_t mrn_open_tables_mutex; +uchar *grn_open_tables_get_key( + MRN_SHARE *share, + size_t *length, + my_bool not_used __attribute__ ((unused)) +) { + DBUG_ENTER("grn_open_tables_get_key"); + *length = share->table_name_length; + DBUG_RETURN((uchar*) share->table_name); +} /* status */ st_mrn_statuses mrn_status_vals; @@ -387,10 +408,21 @@ int mrn_init(void *p) (my_hash_get_key) mrn_allocated_thds_get_key, 0, 0)) { goto error_allocated_thds_hash_init; } + if ((pthread_mutex_init(&mrn_open_tables_mutex, NULL) != 0)) { + goto err_allocated_open_tables_mutex_init; + } + if (my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0, + (my_hash_get_key) grn_open_tables_get_key, 0, 0)) { + goto error_allocated_open_tables_hash_init; + } grn_ctx_fin(ctx); return 0; +error_allocated_open_tables_hash_init: + pthread_mutex_destroy(&mrn_open_tables_mutex); +err_allocated_open_tables_mutex_init: + my_hash_free(&mrn_allocated_thds); error_allocated_thds_hash_init: pthread_mutex_destroy(&mrn_allocated_thds_mutex); err_allocated_thds_mutex_init: @@ -424,6 +456,8 @@ int mrn_deinit(void *p) pthread_mutex_unlock(&mrn_allocated_thds_mutex); } + my_hash_free(&mrn_open_tables); + pthread_mutex_destroy(&mrn_open_tables_mutex); my_hash_free(&mrn_allocated_thds); pthread_mutex_destroy(&mrn_allocated_thds_mutex); pthread_mutex_destroy(&mrn_log_mutex); @@ -898,11 +932,28 @@ ulong ha_mroonga::index_flags(uint idx, uint part, bool all_parts) const } } -int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) +int ha_mroonga::wrapper_create(const char *name, TABLE *table, + HA_CREATE_INFO *info, MRN_SHARE *tmp_share) { - DBUG_ENTER("ha_mroonga::create"); - /* checking data type of virtual columns */ - int i; + int error; + handler *hnd; + DBUG_ENTER("ha_mroonga::wrapper_create"); + /* TODO: create groonga index */ + + if (!(hnd = + tmp_share->hton->create(tmp_share->hton, table->s, + current_thd->mem_root))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + error = hnd->ha_create(name, table, info); + delete hnd; + DBUG_RETURN(error); +} + +int ha_mroonga::default_create(const char *name, TABLE *table, + HA_CREATE_INFO *info, MRN_SHARE *tmp_share) +{ + int error, i; + DBUG_ENTER("ha_mroonga::default_create"); uint n_columns = table->s->fields; for (i = 0; i < n_columns; i++) { Field *field = table->s->field[i]; @@ -918,9 +969,10 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) break; default: GRN_LOG(ctx, GRN_LOG_ERROR, "_id must be numeric data type"); - my_message(ER_CANT_CREATE_TABLE, "_id must be numeric data type", MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); - } + error = ER_CANT_CREATE_TABLE; + my_message(error, "_id must be numeric data type", MYF(0)); + DBUG_RETURN(error); + } } if (strncmp(MRN_SCORE_COL_NAME, col_name, col_name_size) == 0) { switch (field->type()) { @@ -929,9 +981,10 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) break; default: GRN_LOG(ctx, GRN_LOG_ERROR, "_score must be float or double"); - my_message(ER_CANT_CREATE_TABLE, "_score must be float or double", MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); - } + error = ER_CANT_CREATE_TABLE; + my_message(error, "_score must be float or double", MYF(0)); + DBUG_RETURN(error); + } } } @@ -943,8 +996,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) int key_parts = key_info.key_parts; if (key_parts != 1) { GRN_LOG(ctx, GRN_LOG_ERROR, "complex key is not supported yet"); - my_message(ER_NOT_SUPPORTED_YET, "complex key is not supported yet.", MYF(0)); - DBUG_RETURN(ER_NOT_SUPPORTED_YET); + error = ER_NOT_SUPPORTED_YET; + my_message(error, "complex key is not supported yet.", MYF(0)); + DBUG_RETURN(error); } Field *field = key_info.key_part[0].field; const char *col_name = field->field_name; @@ -954,13 +1008,15 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) continue; // hash index is ok } GRN_LOG(ctx, GRN_LOG_ERROR, "only hash index can be defined for _id"); - my_message(ER_CANT_CREATE_TABLE, "only hash index can be defined for _id", MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + error = ER_CANT_CREATE_TABLE; + my_message(error, "only hash index can be defined for _id", MYF(0)); + DBUG_RETURN(error); } if (strncmp(MRN_SCORE_COL_NAME, col_name, col_name_size) == 0) { GRN_LOG(ctx, GRN_LOG_ERROR, "_score cannot be used for index"); - my_message(ER_CANT_CREATE_TABLE, "_score cannot be used for index", MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + error = ER_CANT_CREATE_TABLE; + my_message(error, "_score cannot be used for index", MYF(0)); + DBUG_RETURN(error); } } @@ -980,16 +1036,18 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) db_obj = grn_db_create(ctx, db_path, NULL); if (ctx->rc) { pthread_mutex_unlock(&db_mutex); - my_message(ER_CANT_CREATE_FILE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_FILE); + error = ER_CANT_CREATE_TABLE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } } else { // opening existing database db_obj = grn_db_open(ctx, db_path); if (ctx->rc) { pthread_mutex_unlock(&db_mutex); - my_message(ER_CANT_OPEN_FILE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_OPEN_FILE); + error = ER_CANT_OPEN_FILE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } } mrn_hash_put(ctx, mrn_hash, db_name, db_obj); @@ -1009,8 +1067,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) int key_parts = key_info.key_parts; if (key_parts != 1) { GRN_LOG(ctx, GRN_LOG_ERROR, "complex key is not supported yet"); - my_message(ER_NOT_SUPPORTED_YET, "complex key is not supported yet", MYF(0)); - DBUG_RETURN(ER_NOT_SUPPORTED_YET); + error = ER_NOT_SUPPORTED_YET; + my_message(error, "complex key is not supported yet", MYF(0)); + DBUG_RETURN(error); } Field *pkey_field = key_info.key_part[0].field; const char *col_name = pkey_field->field_name; @@ -1050,8 +1109,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) tbl_obj = grn_table_create(ctx, tbl_name, tbl_name_len, tbl_path, tbl_flags, pkey_type, pkey_value_type); if (ctx->rc) { - my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + error = ER_CANT_CREATE_TABLE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } /* create columns */ @@ -1074,8 +1134,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) col_path, col_flags, col_type); if (ctx->rc) { grn_obj_remove(ctx, tbl_obj); - my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + error = ER_CANT_CREATE_TABLE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } } @@ -1094,8 +1155,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) int key_parts = key_info.key_parts; if (key_parts != 1) { GRN_LOG(ctx, GRN_LOG_ERROR, "complex key is not supported yet"); - my_message(ER_NOT_SUPPORTED_YET, "complex key is not supported yet.", MYF(0)); - DBUG_RETURN(ER_NOT_SUPPORTED_YET); + error = ER_NOT_SUPPORTED_YET; + my_message(error, "complex key is not supported yet.", MYF(0)); + DBUG_RETURN(error); } mrn_index_name_gen(tbl_name, i, idx_name); @@ -1130,8 +1192,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) idx_tbl_flags, col_type, 0); if (ctx->rc) { grn_obj_remove(ctx, tbl_obj); + error = ER_CANT_CREATE_TABLE; my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + DBUG_RETURN(error); } if (key_alg == HA_KEY_ALG_FULLTEXT) { @@ -1146,8 +1209,9 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) if (ctx->rc) { grn_obj_remove(ctx, idx_tbl_obj); grn_obj_remove(ctx, tbl_obj); - my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_CREATE_TABLE); + error = ER_CANT_CREATE_TABLE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } grn_id gid = grn_obj_id(ctx, col_obj); @@ -1159,10 +1223,31 @@ int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) /* clean up */ grn_obj_unlink(ctx, tbl_obj); - DBUG_RETURN(0); } +int ha_mroonga::create(const char *name, TABLE *table, HA_CREATE_INFO *info) +{ + int i, error = 0; + MRN_SHARE *tmp_share; + DBUG_ENTER("ha_mroonga::create"); + /* checking data type of virtual columns */ + + if (!(tmp_share = mrn_get_share(name, table, &error))) + DBUG_RETURN(error); + + if (tmp_share->wrapper_mode) + { + /* create wrapped table */ + error = wrapper_create(name, table, info, tmp_share); + } else { + error = default_create(name, table, info, tmp_share); + } + + mrn_free_share(tmp_share); + DBUG_RETURN(error); +} + int ha_mroonga::open(const char *name, int mode, uint test_if_locked) { DBUG_ENTER("ha_mroonga::open"); @@ -1301,27 +1386,49 @@ int ha_mroonga::close() DBUG_RETURN(0); } -int ha_mroonga::delete_table(const char *name) +int ha_mroonga::wrapper_delete_table(const char *name, MRN_SHARE *tmp_share) { - DBUG_ENTER("ha_mroonga::delete_table"); + int error; + handler *hnd; + DBUG_ENTER("ha_mroonga::wrapper_delete_table"); + if (!(hnd = + tmp_share->hton->create(tmp_share->hton, table->s, + current_thd->mem_root))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + + if ((error = hnd->ha_delete_table(name))) + { + delete hnd; + DBUG_RETURN(error); + } + + /* TODO: create groonga index */ + + delete hnd; + DBUG_RETURN(0); +} + +int ha_mroonga::default_delete_table(const char *name, MRN_SHARE *tmp_share, + const char *tbl_name) +{ + int error; + TABLE_SHARE *tmp_table_share = tmp_share->table_share; + DBUG_ENTER("ha_mroonga::default_delete_table"); char db_path[MRN_MAX_PATH_SIZE]; - char tbl_name[MRN_MAX_PATH_SIZE]; char idx_name[MRN_MAX_PATH_SIZE]; grn_obj *db_obj, *tbl_obj, *lex_obj, *hash_obj, *pat_obj; mrn_db_path_gen(name, db_path); db_obj = grn_db_open(ctx, db_path); if (ctx->rc) { - my_message(ER_CANT_OPEN_FILE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_OPEN_FILE); + error = ER_CANT_OPEN_FILE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } grn_ctx_use(ctx, db_obj); - mrn_table_name_gen(name, tbl_name); - - /* FIXME: remove const 100 */ int i; - for (i = 0; i < 100; i++) { // 100 is enough + for (i = 0; i < tmp_table_share->keys; i++) { mrn_index_name_gen(tbl_name, i, idx_name); grn_obj *idx_tbl_obj = grn_ctx_get(ctx, idx_name, strlen(idx_name)); if (idx_tbl_obj != NULL) { @@ -1331,10 +1438,76 @@ int ha_mroonga::delete_table(const char *name) tbl_obj = grn_ctx_get(ctx, tbl_name, strlen(tbl_name)); if (ctx->rc) { - my_message(ER_CANT_OPEN_FILE, ctx->errbuf, MYF(0)); - DBUG_RETURN(ER_CANT_OPEN_FILE); + error = ER_CANT_OPEN_FILE; + my_message(error, ctx->errbuf, MYF(0)); + DBUG_RETURN(error); } - DBUG_RETURN(grn_obj_remove(ctx, tbl_obj)); + error = grn_obj_remove(ctx, tbl_obj); + DBUG_RETURN(error); +} + +int ha_mroonga::delete_table(const char *name) +{ + int error = 0; + char db_name[MRN_MAX_PATH_SIZE]; + char tbl_name[MRN_MAX_PATH_SIZE]; + TABLE_LIST table_list; + TABLE_SHARE *tmp_table_share; + TABLE tmp_table; + MRN_SHARE *tmp_share; + DBUG_ENTER("ha_mroonga::delete_table"); + mrn_db_name_gen(name, db_name); + mrn_table_name_gen(name, tbl_name); +#if MYSQL_VERSION_ID >= 50500 + table_list.init_one_table(db_name, strlen(db_name), + tbl_name, strlen(tbl_name), tbl_name, TL_WRITE); + mysql_mutex_lock(&LOCK_open); +#else + table_list.init_one_table(db_name, tbl_name, TL_WRITE); + pthread_mutex_lock(&LOCK_open); +#endif + if (!(tmp_table_share = mrn_get_table_share(&table_list, &error))) + { +#if MYSQL_VERSION_ID >= 50500 + mysql_mutex_unlock(&LOCK_open); +#else + pthread_mutex_unlock(&LOCK_open); +#endif + DBUG_RETURN(error); + } +#if MYSQL_VERSION_ID >= 50500 + mysql_mutex_unlock(&LOCK_open); +#else + pthread_mutex_unlock(&LOCK_open); +#endif + tmp_table.s = tmp_table_share; + tmp_table.part_info = NULL; + if (!(tmp_share = mrn_get_share(name, &tmp_table, &error))) + { + mrn_free_table_share(tmp_table_share); + DBUG_RETURN(error); + } + + if (tmp_share->wrapper_mode) + { + error = wrapper_delete_table(name, tmp_share); + } else { + error = default_delete_table(name, tmp_share, tbl_name); + } + + mrn_free_share(tmp_share); +#if MYSQL_VERSION_ID >= 50500 + mysql_mutex_lock(&LOCK_open); +#else + pthread_mutex_lock(&LOCK_open); +#endif + mrn_free_table_share(tmp_table_share); +#if MYSQL_VERSION_ID >= 50500 + mysql_mutex_unlock(&LOCK_open); +#else + pthread_mutex_unlock(&LOCK_open); +#endif + DBUG_RETURN(error); } int ha_mroonga::info(uint flag) Modified: ha_mroonga.h (+7 -0) =================================================================== --- ha_mroonga.h 2011-05-29 13:12:18 +0000 (11ff31a) +++ ha_mroonga.h 2011-06-06 09:55:34 +0000 (9601ead) @@ -203,6 +203,13 @@ private: key_part_map end_key_part_map, bool fulltext); void check_fast_order_limit(); void store_fields_from_primary_table(uchar *buf, grn_id rid); + int wrapper_create(const char *name, TABLE *table, + HA_CREATE_INFO *info, MRN_SHARE *tmp_share); + int default_create(const char *name, TABLE *table, + HA_CREATE_INFO *info, MRN_SHARE *tmp_share); + int wrapper_delete_table(const char *name, MRN_SHARE *tmp_share); + int default_delete_table(const char *name, MRN_SHARE *tmp_share, + const char *tbl_name); }; #ifdef __cplusplus Added: mrn_err.h (+24 -0) 100644 =================================================================== --- /dev/null +++ mrn_err.h 2011-06-06 09:55:34 +0000 (9a79001) @@ -0,0 +1,24 @@ +/* Copyright(C) 2011 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _mrn_err_h +#define _mrn_err_h + +#define ER_MRN_INVALID_TABLE_PARAM_NUM 16501 +#define ER_MRN_INVALID_TABLE_PARAM_STR "The table parameter '%-.64s' is invalid" + +#endif /* _mrn_err_h */ Added: mrn_table.cc (+542 -0) 100644 =================================================================== --- /dev/null +++ mrn_table.cc 2011-06-06 09:55:34 +0000 (91c4dff) @@ -0,0 +1,542 @@ +/* Copyright(C) 2011 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define MYSQL_SERVER 1 +#include "mysql_version.h" +#if MYSQL_VERSION_ID < 50500 +#include "mysql_priv.h" +#include <mysql/plugin.h> +#else +#include "sql_priv.h" +#include "probes_mysql.h" +#include "sql_class.h" +#include "sql_partition.h" +#include "sql_servers.h" +#include "sql_base.h" +#endif +#include "mrn_err.h" +#include "mrnsys.h" +#include "mrn_table.h" + +#define MRN_DEFAULT_STR "DEFAULT" +#define MRN_DEFAULT_LEN (sizeof(MRN_DEFAULT_STR) - 1) +#define MRN_GROONGA_STR "GROONGA" +#define MRN_GROONGA_LEN (sizeof(MRN_GROONGA_STR) - 1) + +extern HASH mrn_open_tables; +extern pthread_mutex_t mrn_open_tables_mutex; + +char *mrn_create_string(const char *str, uint length) +{ + char *res; + DBUG_ENTER("mrn_create_string"); + if (!(res = (char*) my_malloc(length + 1, MYF(MY_WME)))) + DBUG_RETURN(NULL); + memcpy(res, str, length); + res[length] = '\0'; + DBUG_RETURN(res); +} + +char *mrn_get_string_between_quote(char *ptr, bool alloc) +{ + char *start_ptr, *end_ptr, *tmp_ptr, *esc_ptr; + bool find_flg = FALSE, esc_flg = FALSE; + DBUG_ENTER("mrn_get_string_between_quote"); + + start_ptr = strchr(ptr, '\''); + end_ptr = strchr(ptr, '"'); + if (start_ptr && (!end_ptr || start_ptr < end_ptr)) + { + tmp_ptr = ++start_ptr; + while (!find_flg) + { + if (!(end_ptr = strchr(tmp_ptr, '\''))) + DBUG_RETURN(NULL); + esc_ptr = tmp_ptr; + while (!find_flg) + { + esc_ptr = strchr(esc_ptr, '\\'); + if (!esc_ptr || esc_ptr > end_ptr) + find_flg = TRUE; + else if (esc_ptr == end_ptr - 1) + { + esc_flg = TRUE; + tmp_ptr = end_ptr + 1; + break; + } else { + esc_flg = TRUE; + esc_ptr += 2; + } + } + } + } else if (end_ptr) + { + start_ptr = end_ptr; + tmp_ptr = ++start_ptr; + while (!find_flg) + { + if (!(end_ptr = strchr(tmp_ptr, '"'))) + DBUG_RETURN(NULL); + esc_ptr = tmp_ptr; + while (!find_flg) + { + esc_ptr = strchr(esc_ptr, '\\'); + if (!esc_ptr || esc_ptr > end_ptr) + find_flg = TRUE; + else if (esc_ptr == end_ptr - 1) + { + esc_flg = TRUE; + tmp_ptr = end_ptr + 1; + break; + } else { + esc_flg = TRUE; + esc_ptr += 2; + } + } + } + } else + DBUG_RETURN(NULL); + + *end_ptr = '\0'; + if (esc_flg) + { + esc_ptr = start_ptr; + while (TRUE) + { + esc_ptr = strchr(esc_ptr, '\\'); + if (!esc_ptr) + break; + switch(*(esc_ptr + 1)) + { + case 'b': + *esc_ptr = '\b'; + break; + case 'n': + *esc_ptr = '\n'; + break; + case 'r': + *esc_ptr = '\r'; + break; + case 't': + *esc_ptr = '\t'; + break; + default: + *esc_ptr = *(esc_ptr + 1); + break; + } + esc_ptr++; + strcpy(esc_ptr, esc_ptr + 1); + } + } + if (alloc) + { + DBUG_RETURN( + mrn_create_string( + start_ptr, + strlen(start_ptr)) + ); + } else { + DBUG_RETURN(start_ptr); + } +} + +#ifdef WITH_PARTITION_STORAGE_ENGINE +void mrn_get_partition_info(const char *table_name, uint table_name_length, + const TABLE *table, partition_element **part_elem, + partition_element **sub_elem) +{ + char tmp_name[FN_LEN]; + partition_info *part_info = table->part_info; + partition_element *tmp_part_elem = NULL, *tmp_sub_elem = NULL; + bool tmp_flg = FALSE, tmp_find_flg = FALSE; + DBUG_ENTER("mrn_get_partition_info"); + *part_elem = NULL; + *sub_elem = NULL; + if (!part_info) + DBUG_VOID_RETURN; + + if (!memcmp(table_name + table_name_length - 5, "#TMP#", 5)) + tmp_flg = TRUE; + + DBUG_PRINT("info",("mroonga table_name=%s", table_name)); + List_iterator<partition_element> part_it(part_info->partitions); + while ((*part_elem = part_it++)) + { + if ((*part_elem)->subpartitions.elements) + { + List_iterator<partition_element> sub_it((*part_elem)->subpartitions); + while ((*sub_elem = sub_it++)) + { + create_subpartition_name(tmp_name, table->s->path.str, + (*part_elem)->partition_name, (*sub_elem)->partition_name, + NORMAL_PART_NAME); + DBUG_PRINT("info",("mroonga tmp_name=%s", tmp_name)); + if (!memcmp(table_name, tmp_name, table_name_length + 1)) + DBUG_VOID_RETURN; + if ( + tmp_flg && + *(tmp_name + table_name_length - 5) == '\0' && + !memcmp(table_name, tmp_name, table_name_length - 5) + ) { + tmp_part_elem = *part_elem; + tmp_sub_elem = *sub_elem; + tmp_flg = FALSE; + tmp_find_flg = TRUE; + } + } + } else { + create_partition_name(tmp_name, table->s->path.str, + (*part_elem)->partition_name, NORMAL_PART_NAME, TRUE); + DBUG_PRINT("info",("mroonga tmp_name=%s", tmp_name)); + if (!memcmp(table_name, tmp_name, table_name_length + 1)) + DBUG_VOID_RETURN; + if ( + tmp_flg && + *(tmp_name + table_name_length - 5) == '\0' && + !memcmp(table_name, tmp_name, table_name_length - 5) + ) { + tmp_part_elem = *part_elem; + tmp_flg = FALSE; + tmp_find_flg = TRUE; + } + } + } + if (tmp_find_flg) + { + *part_elem = tmp_part_elem; + *sub_elem = tmp_sub_elem; + DBUG_PRINT("info",("mroonga tmp find")); + DBUG_VOID_RETURN; + } + *part_elem = NULL; + *sub_elem = NULL; + DBUG_PRINT("info",("mroonga no hit")); + DBUG_VOID_RETURN; +} +#endif + +#define MRN_PARAM_STR_LEN(name) name ## _length +#define MRN_PARAM_STR(title_name, param_name) \ + if (!strncasecmp(tmp_ptr, title_name, title_length)) \ + { \ + DBUG_PRINT("info",("mroonga "title_name" start")); \ + if (!share->param_name) \ + { \ + if ((share->param_name = mrn_get_string_between_quote( \ + start_ptr, TRUE))) \ + share->MRN_PARAM_STR_LEN(param_name) = strlen(share->param_name); \ + else { \ + error = ER_MRN_INVALID_TABLE_PARAM_NUM; \ + my_printf_error(error, ER_MRN_INVALID_TABLE_PARAM_STR, \ + MYF(0), tmp_ptr); \ + goto error; \ + } \ + DBUG_PRINT("info",("mroonga "title_name"=%s", share->param_name)); \ + } \ + break; \ + } + +int mrn_parse_table_param(MRN_SHARE *share, TABLE *table) +{ + int i, error; + int title_length; + char *param_string = NULL; + char *sprit_ptr[2]; + char *tmp_ptr, *tmp_ptr2, *start_ptr; +#ifdef WITH_PARTITION_STORAGE_ENGINE + partition_element *part_elem; + partition_element *sub_elem; +#endif + DBUG_ENTER("mrn_parse_table_param"); +#ifdef WITH_PARTITION_STORAGE_ENGINE + mrn_get_partition_info(share->table_name, share->table_name_length, table, + &part_elem, &sub_elem); +#endif +#ifdef WITH_PARTITION_STORAGE_ENGINE + for (i = 4; i > 0; i--) +#else + for (i = 2; i > 0; i--) +#endif + { + if (param_string) + { + my_free(param_string, MYF(0)); + param_string = NULL; + } + switch (i) + { +#ifdef WITH_PARTITION_STORAGE_ENGINE + case 4: + if (!sub_elem || !sub_elem->part_comment) + continue; + DBUG_PRINT("info",("mroonga create sub comment string")); + if ( + !(param_string = mrn_create_string( + sub_elem->part_comment, + strlen(sub_elem->part_comment))) + ) { + error = HA_ERR_OUT_OF_MEM; + goto error_alloc_param_string; + } + DBUG_PRINT("info",("mroonga sub comment string=%s", param_string)); + break; + case 3: + if (!part_elem || !part_elem->part_comment) + continue; + DBUG_PRINT("info",("mroonga create part comment string")); + if ( + !(param_string = mrn_create_string( + part_elem->part_comment, + strlen(part_elem->part_comment))) + ) { + error = HA_ERR_OUT_OF_MEM; + goto error_alloc_param_string; + } + DBUG_PRINT("info",("mroonga part comment string=%s", param_string)); + break; +#endif + case 2: + if (table->s->comment.length == 0) + continue; + DBUG_PRINT("info",("mroonga create comment string")); + if ( + !(param_string = mrn_create_string( + table->s->comment.str, + table->s->comment.length)) + ) { + error = HA_ERR_OUT_OF_MEM; + goto error_alloc_param_string; + } + DBUG_PRINT("info",("mroonga comment string=%s", param_string)); + break; + default: + if (table->s->connect_string.length == 0) + continue; + DBUG_PRINT("info",("mroonga create connect_string string")); + if ( + !(param_string = mrn_create_string( + table->s->connect_string.str, + table->s->connect_string.length)) + ) { + error = HA_ERR_OUT_OF_MEM; + goto error_alloc_param_string; + } + DBUG_PRINT("info",("mroonga connect_string=%s", param_string)); + break; + } + + sprit_ptr[0] = param_string; + while (sprit_ptr[0]) + { + if ((sprit_ptr[1] = strchr(sprit_ptr[0], ','))) + { + *sprit_ptr[1] = '\0'; + sprit_ptr[1]++; + } + tmp_ptr = sprit_ptr[0]; + sprit_ptr[0] = sprit_ptr[1]; + while (*tmp_ptr == ' ' || *tmp_ptr == '\r' || + *tmp_ptr == '\n' || *tmp_ptr == '\t') + tmp_ptr++; + + if (*tmp_ptr == '\0') + continue; + + title_length = 0; + start_ptr = tmp_ptr; + while (*start_ptr != ' ' && *start_ptr != '\'' && + *start_ptr != '"' && *start_ptr != '\0' && + *start_ptr != '\r' && *start_ptr != '\n' && + *start_ptr != '\t') + { + title_length++; + start_ptr++; + } + + switch (title_length) + { + case 0: + continue; + case 6: + MRN_PARAM_STR("engine", engine); + error = ER_MRN_INVALID_TABLE_PARAM_NUM; + my_printf_error(error, ER_MRN_INVALID_TABLE_PARAM_STR, + MYF(0), tmp_ptr); + goto error; + default: + error = ER_MRN_INVALID_TABLE_PARAM_NUM; + my_printf_error(error, ER_MRN_INVALID_TABLE_PARAM_STR, + MYF(0), tmp_ptr); + goto error; + } + } + } + + if (share->engine) + { + LEX_STRING engine_name; + if ( + ( + share->engine_length == MRN_DEFAULT_LEN && + !strncasecmp(share->engine, MRN_DEFAULT_STR, MRN_DEFAULT_LEN) + ) || + ( + share->engine_length == MRN_GROONGA_LEN && + !strncasecmp(share->engine, MRN_GROONGA_STR, MRN_GROONGA_LEN) + ) + ) { + my_free(share->engine, MYF(0)); + share->engine = NULL; + share->engine_length = 0; + } else { + engine_name.str = share->engine; + engine_name.length = share->engine_length; + if (!(share->plugin = ha_resolve_by_name(NULL, &engine_name))) + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), share->engine); + error = ER_UNKNOWN_STORAGE_ENGINE; + goto error; + } + share->hton = plugin_data(share->plugin, handlerton *); + share->wrapper_mode = TRUE; + } + } + + if (param_string) + my_free(param_string, MYF(0)); + DBUG_RETURN(0); + +error: + if (param_string) + my_free(param_string, MYF(0)); +error_alloc_param_string: + DBUG_RETURN(error); +} + +int mrn_free_share_alloc( + MRN_SHARE *share +) { + DBUG_ENTER("mrn_free_share_alloc"); + if (share->engine) + my_free(share->engine, MYF(0)); + DBUG_RETURN(0); +} + +MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) +{ + MRN_SHARE *share; + char *tmp_name; + uint length; + DBUG_ENTER("mrn_get_share"); + length = (uint) strlen(table_name); + pthread_mutex_lock(&mrn_open_tables_mutex); + if (!(share = (MRN_SHARE*) my_hash_search(&mrn_open_tables, + (uchar*) table_name, length))) + { + if (!(share = (MRN_SHARE *) + my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &share, sizeof(*share), + &tmp_name, length + 1, + NullS)) + ) { + *error = HA_ERR_OUT_OF_MEM; + goto error_alloc_share; + } + share->use_count = 0; + share->table_name_length = length; + share->table_name = tmp_name; + strmov(share->table_name, table_name); + share->table_share = table->s; + + if ((*error = mrn_parse_table_param(share, table))) + goto error_parse_table_param; + if (pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST)) + { + *error = HA_ERR_OUT_OF_MEM; + goto error_init_mutex; + } + thr_lock_init(&share->lock); + if (my_hash_insert(&mrn_open_tables, (uchar*) share)) + { + *error = HA_ERR_OUT_OF_MEM; + goto error_hash_insert; + } + } + share->use_count++; + pthread_mutex_unlock(&mrn_open_tables_mutex); + DBUG_RETURN(share); + +error_hash_insert: + pthread_mutex_destroy(&share->mutex); +error_init_mutex: +error_parse_table_param: + mrn_free_share_alloc(share); + my_free(share, MYF(0)); +error_alloc_share: + pthread_mutex_unlock(&mrn_open_tables_mutex); + DBUG_RETURN(NULL); +} + +int mrn_free_share(MRN_SHARE *share) +{ + DBUG_ENTER("mrn_free_share"); + pthread_mutex_lock(&mrn_open_tables_mutex); + if (!--share->use_count) + { + my_hash_delete(&mrn_open_tables, (uchar*) share); + if (share->wrapper_mode) + plugin_unlock(NULL, share->plugin); + mrn_free_share_alloc(share); + thr_lock_delete(&share->lock); + pthread_mutex_destroy(&share->mutex); + my_free(share, MYF(0)); + } + pthread_mutex_unlock(&mrn_open_tables_mutex); + DBUG_RETURN(0); +} + +TABLE_SHARE *mrn_get_table_share(TABLE_LIST *table_list, int *error) +{ + char key[MAX_DBKEY_LENGTH]; + uint key_length; + TABLE_SHARE *share; +#if MYSQL_VERSION_ID >= 50500 + my_hash_value_type hash_value; +#endif + THD *thd = current_thd; + DBUG_ENTER("mrn_get_table_share"); + key_length = create_table_def_key(thd, key, table_list, FALSE); +#if MYSQL_VERSION_ID >= 50500 + hash_value = my_calc_hash(&table_def_cache, (uchar*) key, key_length); + share = get_table_share(thd, table_list, key, key_length, 0, error, + hash_value); +#else + share = get_table_share(thd, table_list, key, key_length, 0, error); +#endif + DBUG_RETURN(share); +} + +void mrn_free_table_share(TABLE_SHARE *share) +{ + DBUG_ENTER("mrn_free_table_share"); +#if MYSQL_VERSION_ID >= 50500 + release_table_share(share); +#else + release_table_share(share, RELEASE_NORMAL); +#endif + DBUG_VOID_RETURN; +} Added: mrn_table.h (+54 -0) 100644 =================================================================== --- /dev/null +++ mrn_table.h 2011-06-06 09:55:34 +0000 (d668246) @@ -0,0 +1,54 @@ +/* Copyright(C) 2011 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _mrn_table_h +#define _mrn_table_h + +#if MYSQL_VERSION_ID >= 50500 +#define my_free(A,B) my_free(A) +#endif + +typedef struct st_mroonga_share +{ + char *table_name; + uint table_name_length; + uint use_count; + pthread_mutex_t mutex; + THR_LOCK lock; + TABLE_SHARE *table_share; + + char *engine; + int engine_length; + plugin_ref plugin; + handlerton *hton; + bool wrapper_mode; +} MRN_SHARE; + +char *mrn_create_string(const char *str, uint length); +char *mrn_get_string_between_quote(char *ptr, bool alloc); +#ifdef WITH_PARTITION_STORAGE_ENGINE +void mrn_get_partition_info(const char *table_name, uint table_name_length, + const TABLE *table, partition_element **part_elem, + partition_element **sub_elem); +#endif +int mrn_parse_table_param(MRN_SHARE *share, TABLE *table); +MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error); +int mrn_free_share(MRN_SHARE *share); +TABLE_SHARE *mrn_get_table_share(TABLE_LIST *table_list, int *error); +void mrn_free_table_share(TABLE_SHARE *share); + +#endif /* _mrn_table_h */