summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormonty@mysql.com <>2005-11-05 13:20:35 +0200
committermonty@mysql.com <>2005-11-05 13:20:35 +0200
commitcdf64f0f5724077d58158ecc8894cfff85dbc9c0 (patch)
tree460c9bc04fe66682e1873d2b1e848a224ae7eb8d /sql
parenta6f5375cb0cb40055f52e92d20ca04233ce70386 (diff)
downloadmariadb-git-cdf64f0f5724077d58158ecc8894cfff85dbc9c0.tar.gz
Fix of crashed 5.1 tree (wrong merge + wrong pullout patch forced us to create a new 5.1 tree)
This is a merge of 5.0 -> 5.1 + some code from old 5.1 tree to get all tests to work and keep the .frm format the same as the old 5.1 tree.
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am7
-rw-r--r--sql/ha_heap.h4
-rw-r--r--sql/ha_partition.cc14
-rw-r--r--sql/handler.cc10
-rw-r--r--sql/handler.h6
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/records.cc2
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_partition.cc42
-rw-r--r--sql/sql_plugin.cc622
-rw-r--r--sql/sql_plugin.h63
-rw-r--r--sql/structs.h9
-rw-r--r--sql/table.cc92
-rw-r--r--sql/unireg.cc58
14 files changed, 862 insertions, 70 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 98d4d6b3d3a..f1d43c9c660 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -66,7 +66,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_array.h sql_cursor.h \
examples/ha_example.h ha_archive.h \
examples/ha_tina.h ha_blackhole.h \
- ha_federated.h ha_partition.h
+ ha_federated.h ha_partition.h \
+ sql_plugin.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -104,8 +105,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
examples/ha_example.cc ha_archive.cc \
examples/ha_tina.cc ha_blackhole.cc \
ha_partition.cc sql_partition.cc \
- ha_federated.cc
-
+ ha_federated.cc \
+ sql_plugin.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysql_tzinfo_to_sql_SOURCES = mysql_tzinfo_to_sql.cc
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 24097460a24..4a01b3317f1 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -40,8 +40,8 @@ public:
}
const char *index_type(uint inx)
{
- return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ? "BTREE" :
- "HASH");
+ return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
+ "BTREE" : "HASH");
}
/* Rows also use a fixed-size format */
enum row_type get_row_type() const { return ROW_TYPE_FIXED; }
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5bcd3b8eb52..a7cf6eea49c 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -67,10 +67,10 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE * table);
MODULE create/delete handler object
****************************************************************************/
-static handlerton partition_hton = {
+handlerton partition_hton = {
"partition",
SHOW_OPTION_YES,
- "", /* A comment used by SHOW to describe an engine */
+ "Partition engine", /* A comment used by SHOW to describe an engine */
DB_TYPE_PARTITION_DB,
0, /* Method that initizlizes a storage engine */
0, /* slot */
@@ -701,7 +701,8 @@ bool ha_partition::create_handlers()
bzero(m_file, alloc_len);
for (i= 0; i < m_tot_parts; i++)
{
- if (!(m_file[i]= get_new_handler(table, (enum db_type) m_engine_array[i])))
+ if (!(m_file[i]= get_new_handler(table, current_thd->mem_root,
+ (enum db_type) m_engine_array[i])))
DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]));
}
@@ -727,6 +728,7 @@ bool ha_partition::new_handlers_from_part_info()
partition_element *part_elem;
uint alloc_len= (m_tot_parts + 1) * sizeof(handler*);
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
+ THD *thd= current_thd;
DBUG_ENTER("ha_partition::new_handlers_from_part_info");
if (!(m_file= (handler **) sql_alloc(alloc_len)))
@@ -743,14 +745,16 @@ bool ha_partition::new_handlers_from_part_info()
do
{
part_elem= part_it++;
- if (!(m_file[i]= get_new_handler(table, part_elem->engine_type)))
+ if (!(m_file[i]= get_new_handler(table, thd->mem_root,
+ part_elem->engine_type)))
goto error;
DBUG_PRINT("info", ("engine_type: %u", (uint) part_elem->engine_type));
if (m_is_sub_partitioned)
{
for (j= 0; j < m_part_info->no_subparts; j++)
{
- if (!(m_file[i]= get_new_handler(table, part_elem->engine_type)))
+ if (!(m_file[i]= get_new_handler(table, thd->mem_root,
+ part_elem->engine_type)))
goto error;
DBUG_PRINT("info", ("engine_type: %u", (uint) part_elem->engine_type));
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 1ec4ddf17b7..1b2cae7f7f2 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -62,6 +62,13 @@ handlerton example_hton = { "EXAMPLE", SHOW_OPTION_NO,
#endif
#ifdef HAVE_PARTITION_DB
#include "ha_partition.h"
+extern handlerton partition_hton;
+#else
+handlerton partition_hton = { "partition", SHOW_OPTION_NO,
+ "Partition engine",
+ DB_TYPE_EXAMPLE_DB, NULL, 0, 0, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ HTON_NO_FLAGS };
#endif
#ifdef HAVE_ARCHIVE_DB
#include "ha_archive.h"
@@ -155,6 +162,7 @@ handlerton *sys_table_types[]=
&myisammrg_hton,
&binlog_hton,
&isam_hton,
+ &partition_hton,
NULL
};
@@ -386,6 +394,8 @@ handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type)
delete file;
file=0;
}
+ }
+ return file;
}
diff --git a/sql/handler.h b/sql/handler.h
index 8d749c5fc33..f5f0afa00d5 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -126,7 +126,7 @@
example + csv + heap + blackhole + federated + 0
(yes, the sum is deliberately inaccurate)
*/
-#define MAX_HA 14
+#define MAX_HA 15
/*
Bits in index_ddl_flags(KEY *wanted_index)
@@ -722,8 +722,8 @@ void get_full_part_id_from_key(const TABLE *table, byte *buf,
KEY *key_info,
const key_range *key_spec,
part_id_range *part_spec);
-bool mysql_unpack_partition(File file, THD *thd, uint part_info_len,
- TABLE *table, enum db_type default_db_type);
+bool mysql_unpack_partition(THD *thd, uchar *part_buf, uint part_info_len,
+ TABLE* table, enum db_type default_db_type);
#endif
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a967e2ee7fe..99cf2822ede 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -489,6 +489,7 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
#include "sql_error.h"
#include "field.h" /* Field definitions */
#include "protocol.h"
+#include "sql_plugin.h"
#include "sql_udf.h"
class user_var_entry;
class Security_context;
diff --git a/sql/records.cc b/sql/records.cc
index 4958e39a5a0..ff0185195b0 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -65,7 +65,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
table->status=0; /* And it's always found */
if (!table->file->inited)
{
- table->file->ha_index_init(idx);
+ table->file->ha_index_init(idx, 1);
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
/* read_record will be changed to rr_index in rr_index_first */
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 5c2cc77d66a..ded1c5e5f56 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5540,3 +5540,5 @@ ER_DROP_PARTITION_FAILURE
ER_DROP_PARTITION_WHEN_FK_DEFINED
eng "Cannot drop a partition when a foreign key constraint is defined on the table"
swe "Kan inte ta bort en partition när en främmande nyckel är definierad på tabellen"
+ER_PLUGIN_IS_NOT_LOADED
+ eng "Plugin '%-.64s' is not loaded"
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 906d1cd40a8..ce73061271c 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -42,18 +42,18 @@
/*
Partition related functions declarations and some static constants;
*/
-static char *hash_str= "HASH";
-static char *range_str= "RANGE";
-static char *list_str= "LIST";
-static char *part_str= "PARTITION";
-static char *sub_str= "SUB";
-static char *by_str= "BY";
-static char *key_str= "KEY";
-static char *space_str= " ";
-static char *equal_str= "=";
-static char *end_paren_str= ")";
-static char *begin_paren_str= "(";
-static char *comma_str= ",";
+static const char *hash_str= "HASH";
+static const char *range_str= "RANGE";
+static const char *list_str= "LIST";
+static const char *part_str= "PARTITION";
+static const char *sub_str= "SUB";
+static const char *by_str= "BY";
+static const char *key_str= "KEY";
+static const char *space_str= " ";
+static const char *equal_str= "=";
+static const char *end_paren_str= ")";
+static const char *begin_paren_str= "(";
+static const char *comma_str= ",";
static char buff[22];
bool get_partition_id_list(partition_info *part_info,
@@ -571,7 +571,7 @@ static bool set_up_default_partitions(partition_info *part_info,
if (part_info->part_type != HASH_PARTITION)
{
- char *error_string;
+ const char *error_string;
if (part_info->part_type == RANGE_PARTITION)
error_string= range_str;
else
@@ -1704,7 +1704,7 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table)
}
else
{
- char *error_str;
+ const char *error_str;
if (part_info->part_type == RANGE_PARTITION)
{
error_str= range_str;
@@ -1764,7 +1764,7 @@ end:
static int add_write(File fptr, const char *buf, uint len)
{
- uint len_written= my_write(fptr, buf, len, MYF(0));
+ uint len_written= my_write(fptr, (const byte*)buf, len, MYF(0));
if (likely(len == len_written))
return 0;
else
@@ -2117,7 +2117,7 @@ char *generate_partition_syntax(partition_info *part_info,
if (!buf)
goto close_file;
- if (unlikely(my_read(fptr, buf, *buf_length, MYF(MY_FNABP))))
+ if (unlikely(my_read(fptr, (byte*)buf, *buf_length, MYF(MY_FNABP))))
{
if (!use_sql_alloc)
my_free(buf, MYF(0));
@@ -2896,7 +2896,8 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
{
partition_info *part_info= table->s->part_info;
uint no_parts= get_tot_partitions(part_info), i, part_id;
- uint sub_part= no_parts, part_part= no_parts;
+ uint sub_part= no_parts;
+ uint32 part_part= no_parts;
KEY *key_info= NULL;
bool found_part_field= FALSE;
DBUG_ENTER("get_partition_set");
@@ -3080,17 +3081,14 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
possible to retrace this given an item tree.
*/
-bool mysql_unpack_partition(File file, THD *thd, uint part_info_len,
+bool mysql_unpack_partition(THD *thd, uchar *part_buf, uint part_info_len,
TABLE* table, enum db_type default_db_type)
{
Item *thd_free_list= thd->free_list;
bool result= TRUE;
- uchar* part_buf= NULL;
partition_info *part_info;
LEX *old_lex= thd->lex, lex;
DBUG_ENTER("mysql_unpack_partition");
- if (read_string(file, (gptr*)&part_buf, part_info_len))
- DBUG_RETURN(result);
thd->lex= &lex;
lex_start(thd, part_buf, part_info_len);
/*
@@ -3160,7 +3158,6 @@ bool mysql_unpack_partition(File file, THD *thd, uint part_info_len,
result= FALSE;
end:
thd->free_list= thd_free_list;
- x_free((gptr)part_buf);
thd->lex= old_lex;
DBUG_RETURN(result);
}
@@ -3229,4 +3226,3 @@ void set_key_field_ptr(KEY *key_info, const byte *new_buf,
} while (++i < key_parts);
DBUG_VOID_RETURN;
}
-
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
new file mode 100644
index 00000000000..efe8f256af5
--- /dev/null
+++ b/sql/sql_plugin.cc
@@ -0,0 +1,622 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysql_priv.h"
+#include <my_pthread.h>
+#define REPORT_TO_LOG 1
+#define REPORT_TO_USER 2
+
+char *opt_plugin_dir_ptr;
+char opt_plugin_dir[FN_REFLEN];
+
+static const char *plugin_interface_version_sym=
+ "_mysql_plugin_interface_version_";
+static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
+static int min_plugin_interface_version= 0x0000;
+
+static DYNAMIC_ARRAY plugin_dl_array;
+static DYNAMIC_ARRAY plugin_array;
+static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
+static rw_lock_t THR_LOCK_plugin;
+static bool initialized= 0;
+
+
+static struct st_plugin_dl *plugin_dl_find(LEX_STRING *dl)
+{
+ uint i;
+ DBUG_ENTER("plugin_dl_find");
+ for (i= 0; i < plugin_dl_array.elements; i++)
+ {
+ struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i,
+ struct st_plugin_dl *);
+ if (tmp->ref_count &&
+ ! my_strnncoll(files_charset_info,
+ (const uchar *)dl->str, dl->length,
+ (const uchar *)tmp->dl.str, tmp->dl.length))
+ DBUG_RETURN(tmp);
+ }
+ DBUG_RETURN(0);
+}
+
+
+static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report)
+{
+#ifdef HAVE_DLOPEN
+ char dlpath[FN_REFLEN];
+ uint plugin_dir_len, dummy_errors;
+ struct st_plugin_dl *tmp, plugin_dl;
+ void *sym;
+ DBUG_ENTER("plugin_dl_add");
+ plugin_dir_len= strlen(opt_plugin_dir);
+ /*
+ Ensure that the dll doesn't have a path.
+ This is done to ensure that only approved libraries from the
+ plugin directory are used (to make this even remotely secure).
+ */
+ if (my_strchr(files_charset_info, dl->str, dl->str + dl->length, FN_LIBCHAR) ||
+ dl->length > NAME_LEN ||
+ plugin_dir_len + dl->length + 1 >= FN_REFLEN)
+ {
+ if (report & REPORT_TO_USER)
+ my_error(ER_UDF_NO_PATHS, MYF(0));
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_UDF_NO_PATHS));
+ DBUG_RETURN(0);
+ }
+ /* If this dll is already loaded just increase ref_count. */
+ if ((tmp= plugin_dl_find(dl)))
+ {
+ tmp->ref_count++;
+ DBUG_RETURN(tmp);
+ }
+ /* Compile dll path */
+ strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS);
+ plugin_dl.ref_count= 1;
+ /* Open new dll handle */
+ if (!(plugin_dl.handle= dlopen(dlpath, RTLD_NOW)))
+ {
+ if (report & REPORT_TO_USER)
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, dlerror());
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, errno, dlerror());
+ DBUG_RETURN(0);
+ }
+ /* Determine interface version */
+ if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
+ {
+ dlclose(plugin_dl.handle);
+ if (report & REPORT_TO_USER)
+ my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym);
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_interface_version_sym);
+ DBUG_RETURN(0);
+ }
+ plugin_dl.version= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl.version < min_plugin_interface_version ||
+ (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ dlclose(plugin_dl.handle);
+ if (report & REPORT_TO_USER)
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0,
+ "plugin interface version mismatch");
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_CANT_OPEN_LIBRARY), dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(0);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
+ {
+ dlclose(plugin_dl.handle);
+ if (report & REPORT_TO_USER)
+ my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
+ DBUG_RETURN(0);
+ }
+ plugin_dl.plugins= (struct st_mysql_plugin *)sym;
+ /* Duplicate and convert dll name */
+ plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
+ if (! (plugin_dl.dl.str= my_malloc(plugin_dl.dl.length, MYF(0))))
+ {
+ dlclose(plugin_dl.handle);
+ if (report & REPORT_TO_USER)
+ my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
+ DBUG_RETURN(0);
+ }
+ plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
+ files_charset_info, dl->str, dl->length, system_charset_info,
+ &dummy_errors);
+ plugin_dl.dl.str[plugin_dl.dl.length]= 0;
+ /* Add this dll to array */
+ if (insert_dynamic(&plugin_dl_array, (gptr)&plugin_dl))
+ {
+ dlclose(plugin_dl.handle);
+ my_free(plugin_dl.dl.str, MYF(0));
+ if (report & REPORT_TO_USER)
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
+ struct st_plugin_dl *));
+#else
+ DBUG_ENTER("plugin_dl_add");
+ if (report & REPORT_TO_USER)
+ my_error(ER_FEATURE_DISABLED, MYF(0), "plugin", "HAVE_DLOPEN");
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN");
+ DBUG_RETURN(0);
+#endif
+}
+
+
+static void plugin_dl_del(LEX_STRING *dl)
+{
+#ifdef HAVE_DLOPEN
+ uint i;
+ DBUG_ENTER("plugin_dl_del");
+ for (i= 0; i < plugin_dl_array.elements; i++)
+ {
+ struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i,
+ struct st_plugin_dl *);
+ if (tmp->ref_count &&
+ ! my_strnncoll(files_charset_info,
+ (const uchar *)dl->str, dl->length,
+ (const uchar *)tmp->dl.str, tmp->dl.length))
+ {
+ /* Do not remove this element, unless no other plugin uses this dll. */
+ if (! --tmp->ref_count)
+ {
+ dlclose(tmp->handle);
+ my_free(tmp->dl.str, MYF(0));
+ bzero(tmp, sizeof(struct st_plugin_dl));
+ }
+ break;
+ }
+ }
+ DBUG_VOID_RETURN;
+#endif
+}
+
+
+static struct st_plugin_int *plugin_find_internal(LEX_STRING *name, int type)
+{
+ uint i;
+ DBUG_ENTER("plugin_find_internal");
+ if (! initialized)
+ DBUG_RETURN(0);
+ if (type == MYSQL_ANY_PLUGIN)
+ {
+ for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ {
+ struct st_plugin_int *plugin= (st_plugin_int *)
+ hash_search(&plugin_hash[i], name->str, name->length);
+ if (plugin)
+ DBUG_RETURN(plugin);
+ }
+ }
+ else
+ DBUG_RETURN((st_plugin_int *)
+ hash_search(&plugin_hash[type], name->str, name->length));
+ DBUG_RETURN(0);
+}
+
+
+my_bool plugin_is_ready(LEX_STRING *name, int type)
+{
+ my_bool rc= FALSE;
+ struct st_plugin_int *plugin;
+ DBUG_ENTER("plugin_is_ready");
+ rw_rdlock(&THR_LOCK_plugin);
+ if ((plugin= plugin_find_internal(name, type)) &&
+ plugin->state == PLUGIN_IS_READY)
+ rc= TRUE;
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(rc);
+}
+
+
+struct st_plugin_int *plugin_lock(LEX_STRING *name, int type)
+{
+ struct st_plugin_int *rc;
+ DBUG_ENTER("plugin_find");
+ rw_wrlock(&THR_LOCK_plugin);
+ if ((rc= plugin_find_internal(name, type)))
+ {
+ if (rc->state == PLUGIN_IS_READY)
+ rc->ref_count++;
+ else
+ rc= 0;
+ }
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(rc);
+}
+
+
+static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report)
+{
+ struct st_plugin_int tmp;
+ struct st_mysql_plugin *plugin;
+ DBUG_ENTER("plugin_add");
+ if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
+ {
+ if (report & REPORT_TO_USER)
+ my_error(ER_UDF_EXISTS, MYF(0), name->str);
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_UDF_EXISTS), name->str);
+ DBUG_RETURN(TRUE);
+ }
+ if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
+ DBUG_RETURN(TRUE);
+ /* Find plugin by name */
+ for (plugin= tmp.plugin_dl->plugins; plugin->info; plugin++)
+ {
+ uint name_len= strlen(plugin->name);
+ if (plugin->type >= 0 && plugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
+ ! my_strnncoll(system_charset_info,
+ (const uchar *)name->str, name->length,
+ (const uchar *)plugin->name,
+ name_len))
+ {
+ tmp.plugin= plugin;
+ tmp.name.str= (char *)plugin->name;
+ tmp.name.length= name_len;
+ tmp.ref_count= 0;
+ tmp.state= PLUGIN_IS_UNINITIALIZED;
+ if (insert_dynamic(&plugin_array, (gptr)&tmp))
+ {
+ if (report & REPORT_TO_USER)
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int));
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int));
+ goto err;
+ }
+ if (my_hash_insert(&plugin_hash[plugin->type],
+ (byte*)dynamic_element(&plugin_array,
+ plugin_array.elements - 1,
+ struct st_plugin_int *)))
+ {
+ struct st_plugin_int *tmp_plugin= dynamic_element(&plugin_array,
+ plugin_array.elements - 1, struct st_plugin_int *);
+ tmp_plugin->state= PLUGIN_IS_FREED;
+ if (report & REPORT_TO_USER)
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int));
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int));
+ goto err;
+ }
+ DBUG_RETURN(FALSE);
+ }
+ }
+ if (report & REPORT_TO_USER)
+ my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
+ if (report & REPORT_TO_LOG)
+ sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
+err:
+ plugin_dl_del(dl);
+ DBUG_RETURN(TRUE);
+}
+
+
+static void plugin_del(LEX_STRING *name)
+{
+ uint i;
+ struct st_plugin_int *plugin;
+ DBUG_ENTER("plugin_del");
+ if ((plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ {
+ hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
+ plugin_dl_del(&plugin->plugin_dl->dl);
+ plugin->state= PLUGIN_IS_FREED;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void plugin_unlock(struct st_plugin_int *plugin)
+{
+ DBUG_ENTER("plugin_release");
+ rw_wrlock(&THR_LOCK_plugin);
+ DBUG_ASSERT(plugin && plugin->ref_count);
+ plugin->ref_count--;
+ if (plugin->state == PLUGIN_IS_DELETED && ! plugin->ref_count)
+ {
+ if (plugin->plugin->deinit)
+ plugin->plugin->deinit();
+ plugin_del(&plugin->name);
+ }
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_VOID_RETURN;
+}
+
+
+static void plugin_call_initializer(void)
+{
+ uint i;
+ DBUG_ENTER("plugin_call_initializer");
+ for (i= 0; i < plugin_array.elements; i++)
+ {
+ struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
+ struct st_plugin_int *);
+ if (tmp->state == PLUGIN_IS_UNINITIALIZED && tmp->plugin->init)
+ {
+ DBUG_PRINT("info", ("Initializing plugin: '%s'", tmp->name.str));
+ if (tmp->plugin->init())
+ {
+ sql_print_error("Plugin '%s' init function returned error.",
+ tmp->name.str);
+ DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
+ tmp->name.str))
+ plugin_del(&tmp->name);
+ }
+ }
+ if (tmp->state == PLUGIN_IS_UNINITIALIZED)
+ tmp->state= PLUGIN_IS_READY;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static void plugin_call_deinitializer(void)
+{
+ uint i;
+ DBUG_ENTER("plugin_call_deinitializer");
+ for (i= 0; i < plugin_array.elements; i++)
+ {
+ struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
+ struct st_plugin_int *);
+ if (tmp->state == PLUGIN_IS_READY)
+ {
+ if (tmp->plugin->deinit)
+ {
+ DBUG_PRINT("info", ("Deinitializing plugin: '%s'", tmp->name.str));
+ if (tmp->plugin->deinit())
+ {
+ DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
+ tmp->name.str))
+ }
+ }
+ tmp->state= PLUGIN_IS_UNINITIALIZED;
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static byte *get_hash_key(const byte *buff, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ struct st_plugin_int *plugin= (st_plugin_int *)buff;
+ *length= (uint)plugin->name.length;
+ return((byte *)plugin->name.str);
+}
+
+
+void plugin_init(void)
+{
+ TABLE_LIST tables;
+ TABLE *table;
+ READ_RECORD read_record_info;
+ int error, i;
+ MEM_ROOT mem;
+ DBUG_ENTER("plugin_init");
+ if (initialized)
+ DBUG_VOID_RETURN;
+ my_rwlock_init(&THR_LOCK_plugin, NULL);
+ THD *new_thd = new THD;
+ if (!new_thd ||
+ my_init_dynamic_array(&plugin_dl_array,sizeof(struct st_plugin_dl),16,16) ||
+ my_init_dynamic_array(&plugin_array,sizeof(struct st_plugin_int),16,16))
+ {
+ sql_print_error("Can't allocate memory for plugin structures");
+ delete new_thd;
+ delete_dynamic(&plugin_dl_array);
+ delete_dynamic(&plugin_array);
+ DBUG_VOID_RETURN;
+ }
+ for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ {
+ if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
+ get_hash_key, NULL, 0))
+ {
+ sql_print_error("Can't allocate memory for plugin structures");
+ delete new_thd;
+ delete_dynamic(&plugin_dl_array);
+ delete_dynamic(&plugin_array);
+ DBUG_VOID_RETURN;
+ }
+ }
+ init_sql_alloc(&mem, 1024, 0);
+ initialized= 1;
+ new_thd->store_globals();
+ new_thd->db= my_strdup("mysql", MYF(0));
+ new_thd->db_length= 5;
+ bzero((gptr)&tables, sizeof(tables));
+ tables.alias= tables.table_name= (char*)"plugin";
+ tables.lock_type= TL_READ;
+ tables.db= new_thd->db;
+ if (simple_open_n_lock_tables(new_thd, &tables))
+ {
+ DBUG_PRINT("error",("Can't open plugin table"));
+ sql_print_error("Can't open the mysql.plugin table. Please run the mysql_install_db script to create it.");
+ delete_dynamic(&plugin_dl_array);
+ delete_dynamic(&plugin_array);
+ for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ hash_free(&plugin_hash[i]);
+ goto end;
+ }
+ table= tables.table;
+ init_read_record(&read_record_info, new_thd, table, NULL, 1, 0);
+ while (!(error= read_record_info.read_record(&read_record_info)))
+ {
+ DBUG_PRINT("info", ("init plugin record"));
+ LEX_STRING name, dl;
+ name.str= get_field(&mem, table->field[0]);
+ name.length= strlen(name.str);
+ dl.str= get_field(&mem, table->field[1]);
+ dl.length= strlen(dl.str);
+ if (plugin_add(&name, &dl, REPORT_TO_LOG))
+ DBUG_PRINT("warning", ("Couldn't load plugin named '%s' with soname '%s'.",
+ name.str, dl.str));
+ }
+ plugin_call_initializer();
+ if (error > 0)
+ sql_print_error(ER(ER_GET_ERRNO), my_errno);
+ end_read_record(&read_record_info);
+ new_thd->version--; // Force close to free memory
+end:
+ free_root(&mem, MYF(0));
+ close_thread_tables(new_thd);
+ delete new_thd;
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ DBUG_VOID_RETURN;
+}
+
+
+void plugin_free(void)
+{
+ uint i;
+ DBUG_ENTER("plugin_free");
+ plugin_call_deinitializer();
+ for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ hash_free(&plugin_hash[i]);
+ delete_dynamic(&plugin_array);
+ for (i= 0; i < plugin_dl_array.elements; i++)
+ {
+ struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i,
+ struct st_plugin_dl *);
+#ifdef HAVE_DLOPEN
+ if (tmp->handle)
+ {
+ dlclose(tmp->handle);
+ my_free(tmp->dl.str, MYF(0));
+ }
+#endif
+ }
+ delete_dynamic(&plugin_dl_array);
+ if (initialized)
+ {
+ initialized= 0;
+ rwlock_destroy(&THR_LOCK_plugin);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
+{
+ TABLE_LIST tables;
+ TABLE *table;
+ int error;
+ struct st_plugin_int *tmp;
+ DBUG_ENTER("mysql_install_plugin");
+ bzero(&tables, sizeof(tables));
+ tables.db= (char *)"mysql";
+ tables.table_name= tables.alias= (char *)"plugin";
+ if (check_table_access(thd, INSERT_ACL, &tables, 0))
+ DBUG_RETURN(TRUE);
+ rw_wrlock(&THR_LOCK_plugin);
+ if (plugin_add(name, dl, REPORT_TO_USER))
+ goto err;
+ tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
+ if (tmp->plugin->init)
+ {
+ if (tmp->plugin->init())
+ {
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
+ "Plugin initialization function failed.");
+ goto err;
+ }
+ tmp->state= PLUGIN_IS_READY;
+ }
+ if (! (table = open_ltable(thd, &tables, TL_WRITE)))
+ goto deinit;
+ restore_record(table, s->default_values);
+ table->field[0]->store(name->str, name->length, system_charset_info);
+ table->field[1]->store(dl->str, dl->length, files_charset_info);
+ error= table->file->write_row(table->record[0]);
+ if (error)
+ {
+ table->file->print_error(error, MYF(0));
+ goto deinit;
+ }
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(FALSE);
+deinit:
+ if (tmp->plugin->deinit)
+ tmp->plugin->deinit();
+err:
+ plugin_del(name);
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(TRUE);
+}
+
+
+my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
+{
+ TABLE *table;
+ TABLE_LIST tables;
+ struct st_plugin_int *plugin;
+ DBUG_ENTER("mysql_uninstall_plugin");
+ rw_wrlock(&THR_LOCK_plugin);
+ if (! (plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
+ goto err;
+ }
+ if (plugin->ref_count)
+ {
+ plugin->state= PLUGIN_IS_DELETED;
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Plugin is not deleted, waiting on tables.");
+ }
+ else
+ {
+ if (plugin->plugin->deinit)
+ plugin->plugin->deinit();
+ plugin_del(name);
+ }
+ bzero(&tables, sizeof(tables));
+ tables.db= (char *)"mysql";
+ tables.table_name= tables.alias= (char *)"plugin";
+ if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+ goto err;
+ table->field[0]->store(name->str, name->length, system_charset_info);
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (! table->file->index_read_idx(table->record[0], 0,
+ (byte *)table->field[0]->ptr,
+ table->key_info[0].key_length,
+ HA_READ_KEY_EXACT))
+ {
+ int error;
+ if ((error= table->file->delete_row(table->record[0])))
+ {
+ table->file->print_error(error, MYF(0));
+ goto err;
+ }
+ }
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(FALSE);
+err:
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(TRUE);
+}
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
new file mode 100644
index 00000000000..8fb186b62de
--- /dev/null
+++ b/sql/sql_plugin.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _sql_plugin_h
+#define _sql_plugin_h
+
+#include <plugin.h>
+
+#define MYSQL_ANY_PLUGIN -1
+
+enum enum_plugin_state
+{
+ PLUGIN_IS_FREED= 0,
+ PLUGIN_IS_DELETED,
+ PLUGIN_IS_UNINITIALIZED,
+ PLUGIN_IS_READY
+};
+
+/* A handle for the dynamic library containing a plugin or plugins. */
+
+struct st_plugin_dl
+{
+ LEX_STRING dl;
+ void *handle;
+ struct st_mysql_plugin *plugins;
+ int version;
+ uint ref_count; /* number of plugins loaded from the library */
+};
+
+/* A handle of a plugin */
+
+struct st_plugin_int
+{
+ LEX_STRING name;
+ struct st_mysql_plugin *plugin;
+ struct st_plugin_dl *plugin_dl;
+ enum enum_plugin_state state;
+ uint ref_count; /* number of threads using the plugin */
+};
+
+extern char *opt_plugin_dir_ptr;
+extern char opt_plugin_dir[FN_REFLEN];
+extern void plugin_init(void);
+extern void plugin_free(void);
+extern my_bool plugin_is_ready(LEX_STRING *name, int type);
+extern st_plugin_int *plugin_lock(LEX_STRING *name, int type);
+extern void plugin_unlock(struct st_plugin_int *plugin);
+extern my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl);
+extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name);
+#endif
diff --git a/sql/structs.h b/sql/structs.h
index 3c651c491d3..77d0d435154 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -89,6 +89,15 @@ typedef struct st_key {
uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */
enum ha_key_alg algorithm;
+ /*
+ Note that parser is used when the table is opened for use, and
+ parser_name is used when the table is being created.
+ */
+ union
+ {
+ struct st_plugin_int *parser; /* Fulltext [pre]parser */
+ LEX_STRING *parser_name; /* Fulltext [pre]parser name */
+ };
KEY_PART_INFO *key_part;
char *name; /* Name of key */
/*
diff --git a/sql/table.cc b/sql/table.cc
index 776dcdf66fe..a163f671d01 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -70,7 +70,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
int j,error, errarg= 0;
uint rec_buff_length,n_length,int_length,records,key_parts,keys,
interval_count,interval_parts,read_length,db_create_options;
- uint key_info_length, com_length, part_info_len, extra_rec_buf_length;
+ uint key_info_length, com_length, part_info_len=0, extra_rec_buf_length;
ulong pos, record_offset;
char index_file[FN_REFLEN], *names, *keynames, *comment_pos;
uchar head[288],*disk_buff,new_field_pack_flag;
@@ -154,7 +154,6 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
goto err; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
- part_info_len= uint4korr(head+55);
share->frm_version= head[2];
/*
Check if .frm file created by MySQL 5.0. In this case we want to
@@ -311,9 +310,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
{
/* Read extra data segment */
char *buff, *next_chunk, *buff_end;
+ DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= my_malloc(n_length, MYF(MY_WME))))
goto err;
- buff_end= buff + n_length;
if (my_pread(file, (byte*)buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
@@ -328,16 +327,82 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
goto err;
}
next_chunk+= share->connect_string.length + 2;
+ buff_end= buff + n_length;
if (next_chunk + 2 < buff_end)
{
uint str_db_type_length= uint2korr(next_chunk);
- share->db_type= ha_resolve_by_name(next_chunk + 2, str_db_type_length);
- DBUG_PRINT("enter", ("Setting dbtype to: %d - %d - '%.*s'\n",
- share->db_type,
- str_db_type_length, str_db_type_length,
- next_chunk + 2));
+ enum db_type tmp_db_type= ha_resolve_by_name(next_chunk + 2,
+ str_db_type_length);
+ if (tmp_db_type != DB_TYPE_UNKNOWN)
+ {
+ share->db_type= tmp_db_type;
+ DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
+ str_db_type_length, next_chunk + 2,
+ share->db_type));
+ }
+#ifdef HAVE_PARTITION_DB
+ else
+ {
+ if (!strncmp(next_chunk + 2, "partition", str_db_type_length))
+ {
+ /* Use partition handler */
+ share->db_type= DB_TYPE_PARTITION_DB;
+ DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
+ str_db_type_length, next_chunk + 2,
+ share->db_type));
+ }
+ }
+#endif
next_chunk+= str_db_type_length + 2;
}
+ if (next_chunk + 4 < buff_end)
+ {
+ part_info_len= uint4korr(next_chunk);
+ if (part_info_len > 0)
+ {
+#ifdef HAVE_PARTITION_DB
+ if (mysql_unpack_partition(thd, (uchar *)(next_chunk + 4),
+ part_info_len, outparam,
+ default_part_db_type))
+ {
+ DBUG_PRINT("info", ("mysql_unpack_partition failed"));
+ my_free(buff, MYF(0));
+ goto err;
+ }
+#else
+ DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
+ my_free(buff, MYF(0));
+ goto err;
+#endif
+ }
+ next_chunk+= part_info_len + 5;
+ }
+ keyinfo= outparam->key_info;
+ for (i= 0; i < keys; i++, keyinfo++)
+ {
+ if (keyinfo->flags & HA_USES_PARSER)
+ {
+ LEX_STRING parser_name;
+ if (next_chunk >= buff_end)
+ {
+ DBUG_PRINT("EDS",
+ ("fulltext key uses parser that is not defined in .frm"));
+ my_free(buff, MYF(0));
+ goto err;
+ }
+ parser_name.str= next_chunk;
+ parser_name.length= strlen(next_chunk);
+ keyinfo->parser= plugin_lock(&parser_name, MYSQL_FTPARSER_PLUGIN);
+ if (! keyinfo->parser)
+ {
+ DBUG_PRINT("EDS", ("parser plugin is not loaded"));
+ my_free(buff, MYF(0));
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
+ error_reported= 1;
+ goto err;
+ }
+ }
+ }
my_free(buff, MYF(0));
}
@@ -471,16 +536,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (keynames)
fix_type_pointers(&int_array, &share->keynames, 1, &keynames);
- if (part_info_len > 0)
- {
-#ifdef HAVE_PARTITION_DB
- if (mysql_unpack_partition(file, thd, part_info_len,
- outparam, default_part_db_type))
- goto err;
-#else
- goto err;
-#endif
- }
+
VOID(my_close(file,MYF(MY_WME)));
file= -1;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 86f4b49292a..32f533a6072 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -77,14 +77,14 @@ bool mysql_create_frm(THD *thd, my_string file_name,
handler *db_file)
{
LEX_STRING str_db_type;
- uint reclength,info_length,screens,key_info_length,maxlength;
+ uint reclength,info_length,screens,key_info_length,maxlength,i;
ulong key_buff_length;
File file;
ulong filepos, data_offset;
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
- char buff[2];
+ char buff[5];
#ifdef HAVE_PARTITION_DB
partition_info *part_info= thd->lex->part_info;
#endif
@@ -127,8 +127,21 @@ bool mysql_create_frm(THD *thd, my_string file_name,
/* Calculate extra data segment length */
str_db_type.str= (char *) ha_get_storage_engine(create_info->db_type);
str_db_type.length= strlen(str_db_type.str);
+ /* str_db_type */
create_info->extra_size= (2 + str_db_type.length +
2 + create_info->connect_string.length);
+ /* Partition */
+ create_info->extra_size+= 5;
+#ifdef HAVE_PARTITION_DB
+ if (part_info)
+ create_info->extra_size+= part_info->part_info_len;
+#endif
+
+ for (i= 0; i < keys; i++)
+ {
+ if (key_info[i].parser_name)
+ create_info->extra_size+= key_info[i].parser_name->length + 1;
+ }
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
@@ -155,10 +168,7 @@ bool mysql_create_frm(THD *thd, my_string file_name,
#ifdef HAVE_PARTITION_DB
if (part_info)
- {
- int4store(fileinfo+55,part_info->part_info_len);
fileinfo[61]= (uchar) part_info->default_engine_type;
- }
#endif
int2store(fileinfo+59,db_file->extra_rec_buf_length());
if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
@@ -173,31 +183,49 @@ bool mysql_create_frm(THD *thd, my_string file_name,
goto err;
int2store(buff, create_info->connect_string.length);
- if (my_write(file, (const byte*)buff, sizeof(buff), MYF(MY_NABP)) ||
+ if (my_write(file, (const byte*)buff, 2, MYF(MY_NABP)) ||
my_write(file, (const byte*)create_info->connect_string.str,
create_info->connect_string.length, MYF(MY_NABP)))
goto err;
int2store(buff, str_db_type.length);
- if (my_write(file, (const byte*)buff, sizeof(buff), MYF(MY_NABP)) ||
+ if (my_write(file, (const byte*)buff, 2, MYF(MY_NABP)) ||
my_write(file, (const byte*)str_db_type.str,
str_db_type.length, MYF(MY_NABP)))
goto err;
-
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- if (my_write(file,(byte*) forminfo,288,MYF_RW) ||
- my_write(file,(byte*) screen_buff,info_length,MYF_RW) ||
- pack_fields(file, create_fields, data_offset))
- goto err;
#ifdef HAVE_PARTITION_DB
if (part_info)
{
- if (my_write(file, (byte*) part_info->part_info_string,
- part_info->part_info_len, MYF_RW))
+ int4store(buff, part_info->part_info_len);
+ if (my_write(file, (const byte*)buff, 4, MYF_RW) ||
+ my_write(file, (const byte*)part_info->part_info_string,
+ part_info->part_info_len + 1, MYF_RW))
goto err;
}
+ else
#endif
+ {
+ bzero(buff, 5);
+ if (my_write(file, (byte*) buff, 5, MYF_RW))
+ goto err;
+ }
+ for (i= 0; i < keys; i++)
+ {
+ if (key_info[i].parser_name)
+ {
+ if (my_write(file, (const byte*)key_info[i].parser_name->str,
+ key_info[i].parser_name->length + 1, MYF(MY_NABP)))
+ goto err;
+ }
+ }
+
+ VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
+ if (my_write(file,(byte*) forminfo,288,MYF_RW) ||
+ my_write(file,(byte*) screen_buff,info_length,MYF_RW) ||
+ pack_fields(file, create_fields, data_offset))
+ goto err;
+
#ifdef HAVE_CRYPTED_FRM
if (create_info->password)
{