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.
This commit is contained in:
parent
a6f5375cb0
commit
cdf64f0f57
@ -1537,3 +1537,4 @@ vio/test-ssl
|
||||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
libmysqld/sql_plugin.cc
|
||||
|
@ -22,7 +22,7 @@ pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \
|
||||
errmsg.h my_global.h my_net.h my_alloc.h \
|
||||
my_getopt.h sslopt-longopts.h my_dir.h typelib.h \
|
||||
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
|
||||
mysql_time.h $(BUILT_SOURCES)
|
||||
mysql_time.h plugin.h $(BUILT_SOURCES)
|
||||
noinst_HEADERS = config-win.h config-os2.h config-netware.h \
|
||||
heap.h my_bitmap.h\
|
||||
myisam.h myisampack.h myisammrg.h ft_global.h\
|
||||
|
@ -399,6 +399,8 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
|
||||
|
||||
extern my_bool my_parse_charset_xml(const char *bug, uint len,
|
||||
int (*add)(CHARSET_INFO *cs));
|
||||
extern char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end,
|
||||
char c);
|
||||
|
||||
my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, uint len);
|
||||
my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
|
||||
|
@ -209,12 +209,8 @@ enum ha_base_keytype {
|
||||
#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */
|
||||
#define HA_VAR_LENGTH_KEY 8
|
||||
#define HA_NULL_PART_KEY 64
|
||||
#ifndef ISAM_LIBRARY
|
||||
#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */
|
||||
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
|
||||
#else
|
||||
/* poor old NISAM has 8-bit flags :-( */
|
||||
#define HA_SORT_ALLOWS_SAME 128 /* Intern bit when sorting records */
|
||||
#endif
|
||||
/*
|
||||
Key has a part that can have end space. If this is an unique key
|
||||
we have to handle it differently from other unique keys as we can find
|
||||
|
181
include/plugin.h
Normal file
181
include/plugin.h
Normal file
@ -0,0 +1,181 @@
|
||||
/* 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 _my_plugin_h
|
||||
#define _my_plugin_h
|
||||
|
||||
/*************************************************************************
|
||||
Plugin API. Common for all plugin types.
|
||||
*/
|
||||
|
||||
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0000
|
||||
|
||||
/*
|
||||
The allowable types of plugins
|
||||
*/
|
||||
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */
|
||||
#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */
|
||||
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text [pre]parser */
|
||||
#define MYSQL_MAX_PLUGIN_TYPE_NUM 3 /* The number of plugin types */
|
||||
|
||||
/*
|
||||
Macros for beginning and ending plugin declarations. Between
|
||||
mysql_declare_plugin and mysql_declare_plugin_end there should
|
||||
be a st_mysql_plugin struct for each plugin to be declared.
|
||||
*/
|
||||
|
||||
#define mysql_declare_plugin \
|
||||
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
|
||||
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
|
||||
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0}}
|
||||
|
||||
/*
|
||||
Plugin description structure.
|
||||
*/
|
||||
|
||||
struct st_mysql_plugin
|
||||
{
|
||||
int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
|
||||
void *info; /* pointer to type-specific plugin descriptor */
|
||||
const char *name; /* plugin name */
|
||||
const char *author; /* plugin author (for SHOW PLUGINS) */
|
||||
const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
|
||||
int (*init)(void); /* the function to invoke when plugin is loaded */
|
||||
int (*deinit)(void); /* the function to invoke when plugin is unloaded */
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
API for Full-text [pre]parser plugin. (MYSQL_FTPARSER_PLUGIN)
|
||||
*/
|
||||
|
||||
#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0000
|
||||
|
||||
/* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */
|
||||
/*
|
||||
The fast and simple mode. Parser is expected to return only those words that
|
||||
go into the index. Stopwords or too short/long words should not be returned.
|
||||
'boolean_info' argument of mysql_add_word() does not have to be set.
|
||||
|
||||
This mode is used for indexing, and natural language queries.
|
||||
*/
|
||||
#define MYSQL_FTPARSER_SIMPLE_MODE 0
|
||||
|
||||
/*
|
||||
The parser is not allowed to ignore words in this mode. Every word should
|
||||
be returned, including stopwords and words that are too short or long.
|
||||
'boolean_info' argument of mysql_add_word() does not have to be set.
|
||||
|
||||
This mode is used in boolean searches for "phrase matching."
|
||||
*/
|
||||
#define MYSQL_FTPARSER_WITH_STOPWORDS 1
|
||||
|
||||
/*
|
||||
Parse in boolean mode. The parser should provide a valid
|
||||
MYSQL_FTPARSER_BOOLEAN_INFO structure in the 'boolean_info' argument
|
||||
to mysql_add_word(). Usually that means that the parser should
|
||||
recognize boolean operators in the parsing stream and set appropriate
|
||||
fields in MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly. As
|
||||
for MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored.
|
||||
Instead, use FT_TOKEN_STOPWORD for the token type of such a word.
|
||||
|
||||
This mode is used to parse a boolean query string.
|
||||
*/
|
||||
#define MYSQL_FTPARSER_FULL_BOOLEAN_INFO 2
|
||||
|
||||
enum enum_ft_token_type
|
||||
{
|
||||
FT_TOKEN_EOF= 0,
|
||||
FT_TOKEN_WORD= 1,
|
||||
FT_TOKEN_LEFT_PAREN= 2,
|
||||
FT_TOKEN_RIGHT_PAREN= 3,
|
||||
FT_TOKEN_STOPWORD= 4
|
||||
};
|
||||
|
||||
/*
|
||||
This structure is used in boolean search mode only. It conveys
|
||||
boolean-mode metadata to the MySQL search engine for every word in
|
||||
the search query. A valid instance of this structure must be filled
|
||||
in by the plugin parser and passed as an argument in the call to
|
||||
mysql_add_word (the function from structure MYSQL_FTPARSER_PARAM)
|
||||
when a query is parsed in boolean mode.
|
||||
*/
|
||||
|
||||
typedef struct st_mysql_ftparser_boolean_info
|
||||
{
|
||||
enum enum_ft_token_type type;
|
||||
int yesno;
|
||||
int weight_adjust;
|
||||
bool wasign;
|
||||
bool trunc;
|
||||
/* These are parser state and must be removed. */
|
||||
byte prev;
|
||||
byte *quot;
|
||||
} MYSQL_FTPARSER_BOOLEAN_INFO;
|
||||
|
||||
|
||||
/*
|
||||
An argument of the full-text parser plugin. This structure is
|
||||
filled by MySQL server and passed to the parsing function of the
|
||||
plugin as an in/out parameter.
|
||||
*/
|
||||
|
||||
typedef struct st_mysql_ftparser_param
|
||||
{
|
||||
/*
|
||||
A fallback pointer to the built-in parser implementation
|
||||
of the server. It's set by the server and can be used
|
||||
by the parser plugin to invoke the MySQL default parser.
|
||||
If plugin's role is to extract textual data from .doc,
|
||||
.pdf or .xml content, it might use the default MySQL parser
|
||||
to parse the extracted plaintext string.
|
||||
*/
|
||||
int (*mysql_parse)(void *param, byte *doc, uint doc_len);
|
||||
/*
|
||||
A server callback to add a new word.
|
||||
When parsing a document, the server sets this to point at
|
||||
a function that adds the word to MySQL full-text index.
|
||||
When parsing a search query, this function will
|
||||
add the new word to the list of words to search for.
|
||||
boolean_info can be NULL for all cases except
|
||||
MYSQL_FTPARSER_FULL_BOOLEAN_INFO mode.
|
||||
*/
|
||||
int (*mysql_add_word)(void *param, byte *word, uint word_len,
|
||||
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
|
||||
/* A pointer to the parser local state. This is an inout parameter. */
|
||||
void *ftparser_state;
|
||||
void *mysql_ftparam;
|
||||
/* Character set of the document or the query */
|
||||
CHARSET_INFO *cs;
|
||||
/* A pointer to the document or the query to be parsed */
|
||||
byte *doc;
|
||||
/* Document/query length */
|
||||
uint length;
|
||||
/*
|
||||
Parsing mode: with boolean operators, with stopwords, or nothing.
|
||||
See MYSQL_FTPARSER_* constants above.
|
||||
*/
|
||||
int mode;
|
||||
} MYSQL_FTPARSER_PARAM;
|
||||
|
||||
struct st_mysql_ftparser
|
||||
{
|
||||
int interface_version;
|
||||
int (*parse)(MYSQL_FTPARSER_PARAM *param);
|
||||
int (*init)(MYSQL_FTPARSER_PARAM *param);
|
||||
int (*deinit)(MYSQL_FTPARSER_PARAM *param);
|
||||
};
|
||||
#endif
|
||||
|
@ -64,7 +64,8 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
||||
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
|
||||
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
|
||||
rpl_filter.cc \
|
||||
ha_blackhole.cc ha_archive.cc sql_partition.cc ha_partition.cc
|
||||
ha_blackhole.cc ha_archive.cc sql_partition.cc ha_partition.cc \
|
||||
sql_plugin.cc
|
||||
|
||||
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
|
||||
libmysqld_a_SOURCES=
|
||||
@ -83,7 +84,6 @@ INC_LIB= $(top_builddir)/regex/libregex.a \
|
||||
$(top_builddir)/dbug/libdbug.a \
|
||||
$(top_builddir)/vio/libvio.a \
|
||||
@yassl_libs_with_path@
|
||||
|
||||
|
||||
#
|
||||
# To make it easy for the end user to use the embedded library we
|
||||
|
@ -13,7 +13,7 @@ Table Create Table
|
||||
gis_point CREATE TABLE `gis_point` (
|
||||
`fid` int(11) default NULL,
|
||||
`g` point default NULL
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
|
||||
) ENGINE=NDBCLUSTER DEFAULT CHARSET=latin1
|
||||
SHOW FIELDS FROM gis_point;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
@ -471,7 +471,7 @@ Table Create Table
|
||||
gis_point CREATE TABLE `gis_point` (
|
||||
`fid` int(11) default NULL,
|
||||
`g` point default NULL
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
|
||||
) ENGINE=NDBCLUSTER DEFAULT CHARSET=latin1
|
||||
SHOW FIELDS FROM gis_point;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
622
sql/sql_plugin.cc
Normal file
622
sql/sql_plugin.cc
Normal file
@ -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);
|
||||
}
|
63
sql/sql_plugin.h
Normal file
63
sql/sql_plugin.h
Normal file
@ -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
|
@ -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 */
|
||||
/*
|
||||
|
92
sql/table.cc
92
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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
#ifdef HAVE_PARTITION_DB
|
||||
if (part_info)
|
||||
{
|
||||
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_PARTITION_DB
|
||||
if (part_info)
|
||||
{
|
||||
if (my_write(file, (byte*) part_info->part_info_string,
|
||||
part_info->part_info_len, MYF_RW))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_CRYPTED_FRM
|
||||
if (create_info->password)
|
||||
{
|
||||
|
@ -22,19 +22,19 @@ pkglib_LIBRARIES = libmystrings.a
|
||||
# Exact one of ASSEMBLER_X
|
||||
if ASSEMBLER_x86
|
||||
ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s
|
||||
CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c
|
||||
CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c my_strchr.c
|
||||
else
|
||||
if ASSEMBLER_sparc32
|
||||
# These file MUST all be on the same line!! Otherwise automake
|
||||
# generats a very broken makefile
|
||||
ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s
|
||||
CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c
|
||||
CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c
|
||||
else
|
||||
#no assembler
|
||||
ASRCS =
|
||||
# These file MUST all be on the same line!! Otherwise automake
|
||||
# generats a very broken makefile
|
||||
CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c
|
||||
CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c my_strchr.c
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -53,7 +53,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc
|
||||
bmove_upp-sparc.s strappend-sparc.s strend-sparc.s \
|
||||
strinstr-sparc.s strmake-sparc.s strmov-sparc.s \
|
||||
strnmov-sparc.s strstr-sparc.s strxmov-sparc.s \
|
||||
t_ctype.h
|
||||
t_ctype.h my_strchr.c
|
||||
|
||||
libmystrings_a_LIBADD=
|
||||
conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c
|
||||
|
48
strings/my_strchr.c
Normal file
48
strings/my_strchr.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* 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 */
|
||||
|
||||
/*
|
||||
my_strchr(cs, str, end, c) returns a pointer to the first place in
|
||||
str where c (1-byte character) occurs, or NULL if c does not occur
|
||||
in str. This function is multi-byte safe.
|
||||
TODO: should be moved to CHARSET_INFO if it's going to be called
|
||||
frequently.
|
||||
*/
|
||||
|
||||
#include <my_global.h>
|
||||
#include "m_string.h"
|
||||
#include "m_ctype.h"
|
||||
|
||||
|
||||
byte *my_strchr(CHARSET_INFO *cs, const char *str, const char *end,
|
||||
char c)
|
||||
{
|
||||
uint mbl;
|
||||
while (str < end)
|
||||
{
|
||||
mbl= my_mbcharlen(cs, *(uchar *)str);
|
||||
if (mbl < 2)
|
||||
{
|
||||
if (*str == c)
|
||||
return((char *)str);
|
||||
str++;
|
||||
}
|
||||
else
|
||||
str+= mbl;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user