diff options
Diffstat (limited to 'libmysqld')
-rw-r--r-- | libmysqld/Makefile.am | 44 | ||||
-rw-r--r-- | libmysqld/emb_qcache.cc | 129 | ||||
-rw-r--r-- | libmysqld/embedded_priv.h | 21 | ||||
-rw-r--r-- | libmysqld/examples/Makefile.am | 20 | ||||
-rw-r--r-- | libmysqld/examples/builder-sample/emb_samples.cpp | 1 | ||||
-rwxr-xr-x | libmysqld/ha_blackhole.cc | 0 | ||||
-rw-r--r-- | libmysqld/lib_sql.cc | 580 | ||||
-rw-r--r-- | libmysqld/libmysqld.c | 27 | ||||
-rw-r--r-- | libmysqld/libmysqld.def | 11 | ||||
-rw-r--r--[-rwxr-xr-x] | libmysqld/libmysqld.rc | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | libmysqld/resource.h | 0 |
11 files changed, 535 insertions, 298 deletions
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index d6f68047296..54eb27be037 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,9 +25,10 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -INCLUDES= @MT_INCLUDES@ @bdb_includes@ \ +INCLUDES= @bdb_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \ + -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \ + -I$(top_srcdir)/regex \ $(openssl_includes) @ZLIB_INCLUDES@ noinst_LIBRARIES = libmysqld_int.a @@ -36,12 +37,12 @@ SUBDIRS = . examples libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \ my_time.c -sqlexamplessources = ha_example.cc ha_archive.cc ha_tina.cc +sqlexamplessources = ha_example.cc ha_tina.cc noinst_HEADERS = embedded_priv.h emb_qcache.h sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ - ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ + ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_federated.cc \ ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \ hostname.cc init.cc password.c \ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \ @@ -59,8 +60,10 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \ sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \ unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \ - spatial.cc gstream.cc sql_help.cc tztime.cc \ - ha_blackhole.cc + spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.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 \ + ha_blackhole.cc ha_archive.cc my_user.c libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) libmysqld_a_SOURCES= @@ -79,33 +82,30 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/vio/libvio.a + # # To make it easy for the end user to use the embedded library we # generate a total libmysqld.a from all library files, +# note - InnoDB libraries have circular dependencies, so in INC_LIB +# few libraries are present two times. Metrowerks linker doesn't like +# it at all. Traditional ar has no problems with it, but still there's no +# need to add the same file twice to the library, so 'sort -u' save us +# some time and spares unnecessary work. + libmysqld.a: libmysqld_int.a $(INC_LIB) if DARWIN_MWCC - mwld -lib -o $@ libmysqld_int.a `ls -1 $(INC_LIB) | sort -u` + mwld -lib -o $@ libmysqld_int.a `echo $(INC_LIB) | sort -u` else + -rm -f libmysqld.a if test "$(host_os)" = "netware" ; \ then \ $(libmysqld_a_AR) libmysqld.a libmysqld_int.a $(INC_LIB) ; \ else \ - if test ! -d tmp ; then mkdir tmp ; fi ; \ - rm -f $@ libmysqld_int2.a tmp/*.o tmp/*.a ; \ - cp $(INC_LIB) tmp ; \ - cp libmysqld_int.a libmysqld_int2.a ; \ - cd tmp ; \ - for file in *.a ; do \ - bfile=`basename $$file .a` ; \ - $(AR) x $$file; \ - for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \ - $(AR) q ../libmysqld_int2.a *.o ; \ - rm -f *.o ; \ - done ; \ - cd .. ; \ - mv libmysqld_int2.a libmysqld.a ; \ - rm -f tmp/* ; \ + for arc in ./libmysqld_int.a $(INC_LIB); do \ + arpath=`echo $$arc|sed 's|[^/]*$$||'`; \ + $(AR) t $$arc|sed "s|^|$$arpath|"; \ + done | sort -u | xargs $(AR) cq libmysqld.a ; \ $(RANLIB) libmysqld.a ; \ fi endif diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc index ecc45096165..078243a6d5e 100644 --- a/libmysqld/emb_qcache.cc +++ b/libmysqld/emb_qcache.cc @@ -18,6 +18,7 @@ #ifdef HAVE_QUERY_CACHE #include <mysql.h> #include "emb_qcache.h" +#include "embedded_priv.h" void Querycache_stream::store_char(char c) { @@ -284,22 +285,25 @@ int Querycache_stream::load_column(MEM_ROOT *alloc, char** column) uint emb_count_querycache_size(THD *thd) { - uint result; - MYSQL *mysql= thd->mysql; - MYSQL_FIELD *field= mysql->fields; - MYSQL_FIELD *field_end= field + mysql->field_count; - MYSQL_ROWS *cur_row=NULL; - my_ulonglong n_rows=0; + uint result= 0; + MYSQL_FIELD *field; + MYSQL_FIELD *field_end; + MYSQL_ROWS *cur_row; + my_ulonglong n_rows; + MYSQL_DATA *data= thd->first_data; + + while (data->embedded_info->next) + data= data->embedded_info->next; + field= data->embedded_info->fields_list; + field_end= field + data->fields; if (!field) - return 0; - if (thd->data) - { - *thd->data->prev_ptr= NULL; // this marks the last record - cur_row= thd->data->data; - n_rows= thd->data->rows; - } - result= (uint) (4+8 + (42 + 4*n_rows)*mysql->field_count); + return result; + *data->embedded_info->prev_ptr= NULL; // this marks the last record + cur_row= data->data; + n_rows= data->rows; + /* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */ + result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields); for(; field < field_end; field++) { @@ -313,34 +317,38 @@ uint emb_count_querycache_size(THD *thd) for (; cur_row; cur_row=cur_row->next) { MYSQL_ROW col= cur_row->data; - MYSQL_ROW col_end= col + mysql->field_count; + MYSQL_ROW col_end= col + data->fields; for (; col < col_end; col++) if (*col) - result+= *(uint *)((*col) - sizeof(uint)); + result+= *(uint *)((*col) - sizeof(uint)); } return result; } void emb_store_querycache_result(Querycache_stream *dst, THD *thd) { - MYSQL *mysql= thd->mysql; - MYSQL_FIELD *field= mysql->fields; - MYSQL_FIELD *field_end= field + mysql->field_count; - MYSQL_ROWS *cur_row= NULL; - my_ulonglong n_rows= 0; + MYSQL_FIELD *field; + MYSQL_FIELD *field_end; + MYSQL_ROWS *cur_row; + my_ulonglong n_rows; + MYSQL_DATA *data= thd->first_data; + + DBUG_ENTER("emb_store_querycache_result"); + + while (data->embedded_info->next) + data= data->embedded_info->next; + field= data->embedded_info->fields_list; + field_end= field + data->fields; if (!field) - return; + DBUG_VOID_RETURN; - if (thd->data) - { - *thd->data->prev_ptr= NULL; // this marks the last record - cur_row= thd->data->data; - n_rows= thd->data->rows; - } + *data->embedded_info->prev_ptr= NULL; // this marks the last record + cur_row= data->data; + n_rows= data->rows; - dst->store_int((uint)mysql->field_count); - dst->store_ll((uint)n_rows); + dst->store_int((uint)data->fields); + dst->store_ll((ulonglong)n_rows); for(; field < field_end; field++) { @@ -356,14 +364,13 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) dst->store_str(field->org_table, field->org_table_length); dst->store_str(field->db, field->db_length); dst->store_str(field->catalog, field->catalog_length); - dst->store_safe_str(field->def, field->def_length); } for (; cur_row; cur_row=cur_row->next) { MYSQL_ROW col= cur_row->data; - MYSQL_ROW col_end= col + mysql->field_count; + MYSQL_ROW col_end= col + data->fields; for (; col < col_end; col++) { uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; @@ -371,28 +378,34 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) } } DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size); + DBUG_VOID_RETURN; } int emb_load_querycache_result(THD *thd, Querycache_stream *src) { - MYSQL *mysql= thd->mysql; - MYSQL_DATA *data; + MYSQL_DATA *data= thd->alloc_new_dataset(); MYSQL_FIELD *field; MYSQL_FIELD *field_end; - MEM_ROOT *f_alloc= &mysql->field_alloc; + MEM_ROOT *f_alloc; MYSQL_ROWS *row, *end_row; MYSQL_ROWS **prev_row; ulonglong rows; MYSQL_ROW columns; + DBUG_ENTER("emb_load_querycache_result"); + + if (!data) + goto err; + init_alloc_root(&data->alloc, 8192,0); + f_alloc= &data->alloc; - mysql->field_count= src->load_int(); + data->fields= src->load_int(); rows= src->load_ll(); if (!(field= (MYSQL_FIELD *) - alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD)))) + alloc_root(f_alloc,data->fields*sizeof(MYSQL_FIELD)))) goto err; - mysql->fields= field; - for(field_end= field+mysql->field_count; field < field_end; field++) + data->embedded_info->fields_list= field; + for(field_end= field+data->fields; field < field_end; field++) { field->length= src->load_int(); field->max_length= (unsigned int)src->load_int(); @@ -402,47 +415,43 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) field->decimals= (unsigned int)src->load_char(); if (!(field->name= src->load_str(f_alloc, &field->name_length)) || - !(field->table= src->load_str(f_alloc,&field->table_length)) || - !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) || - !(field->org_table= src->load_str(f_alloc, &field->org_table_length))|| - !(field->db= src->load_str(f_alloc, &field->db_length)) || - !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) || - src->load_safe_str(f_alloc, &field->def, &field->def_length)) + !(field->table= src->load_str(f_alloc,&field->table_length)) || + !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) || + !(field->org_table= src->load_str(f_alloc, &field->org_table_length))|| + !(field->db= src->load_str(f_alloc, &field->db_length)) || + !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) || + src->load_safe_str(f_alloc, &field->def, &field->def_length)) goto err; } - if (!rows) - return 0; - if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - goto err; - thd->data= data; - init_alloc_root(&data->alloc, 8192,0); - row= (MYSQL_ROWS *)alloc_root(&data->alloc, (uint) (rows * sizeof(MYSQL_ROWS) + - rows * (mysql->field_count+1)*sizeof(char*))); + row= (MYSQL_ROWS *)alloc_root(&data->alloc, + (uint) (rows * sizeof(MYSQL_ROWS) + + rows*(data->fields+1)*sizeof(char*))); end_row= row + rows; columns= (MYSQL_ROW)end_row; data->rows= rows; - data->fields= mysql->field_count; data->data= row; + if (!rows) + goto return_ok; for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) { *prev_row= row; row->data= columns; - MYSQL_ROW col_end= columns + mysql->field_count; + MYSQL_ROW col_end= columns + data->fields; for (; columns < col_end; columns++) src->load_column(&data->alloc, columns); *(columns++)= NULL; } *prev_row= NULL; - data->prev_ptr= prev_row; - - return 0; + data->embedded_info->prev_ptr= prev_row; +return_ok: + send_eof(thd); + DBUG_RETURN(0); err: - return 1; + DBUG_RETURN(1); } #endif /*HAVE_QUERY_CACHE*/ diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h index d4316dff63f..88015340e8c 100644 --- a/libmysqld/embedded_priv.h +++ b/libmysqld/embedded_priv.h @@ -16,18 +16,25 @@ /* Prototypes for the embedded version of MySQL */ -#include <my_global.h> -#include <mysql.h> -#include <mysql_embed.h> -#include <mysqld_error.h> -#include <my_pthread.h> - C_MODE_START void lib_connection_phase(NET *net, int phase); void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db); void *create_embedded_thd(int client_flag, char *db); int check_embedded_connection(MYSQL *mysql); void free_old_query(MYSQL *mysql); -void embedded_get_error(MYSQL *mysql); extern MYSQL_METHODS embedded_methods; + +/* This one is used by embedded library to gather returning data */ +typedef struct embedded_query_result +{ + MYSQL_ROWS **prev_ptr; + unsigned int warning_count, server_status; + struct st_mysql_data *next; + my_ulonglong affected_rows, insert_id; + char info[MYSQL_ERRMSG_SIZE]; + MYSQL_FIELD *fields_list; + unsigned int last_errno; + char sqlstate[SQLSTATE_LENGTH+1]; +} EQR; + C_MODE_END diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am index 588a6153a3b..01429378dfb 100644 --- a/libmysqld/examples/Makefile.am +++ b/libmysqld/examples/Makefile.am @@ -14,10 +14,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -noinst_PROGRAMS = mysql -bin_PROGRAMS = mysqltest_embedded mysql_client_test_embedded -client_sources = $(mysqltest_embedded_SOURCES) $(mysql_SOURCES) -tests_sources= $(mysql_client_test_embedded_SOURCES) +noinst_PROGRAMS = mysql +bin_PROGRAMS = mysqltest_embedded mysql_client_test_embedded +client_sources = $(mysqltest_embedded_SOURCES) $(mysql_SOURCES) +tests_sources = $(mysql_client_test_embedded_SOURCES) +CLEANFILES = $(client_sources) $(tests_sources) link_sources: set -x; \ @@ -31,11 +32,10 @@ link_sources: done DEFS = -DEMBEDDED_LIBRARY -INCLUDES = @MT_INCLUDES@ \ - -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \ +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \ -I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \ $(openssl_includes) -LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ +LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ $(yassl_libs) LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS) mysqltest_embedded_LINK = $(CXXLINK) @@ -47,11 +47,7 @@ mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \ mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) mysql_client_test_embedded_LINK = $(CXXLINK) -mysql_client_test_embedded_SOURCES = mysql_client_test.c - -clean-local: - rm -f $(client_sources) - rm -f $(tests_sources) +mysql_client_test_embedded_SOURCES = mysql_client_test.c # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/libmysqld/examples/builder-sample/emb_samples.cpp b/libmysqld/examples/builder-sample/emb_samples.cpp index 4dfde111f84..411de26149b 100644 --- a/libmysqld/examples/builder-sample/emb_samples.cpp +++ b/libmysqld/examples/builder-sample/emb_samples.cpp @@ -109,6 +109,7 @@ bool __fastcall TForm1::connect_server() ret_value = true; is_server_started = true; } + MySQL->reconnect= 1; return ret_value; } //--------------------------------------------------------------------------- diff --git a/libmysqld/ha_blackhole.cc b/libmysqld/ha_blackhole.cc deleted file mode 100755 index e69de29bb2d..00000000000 --- a/libmysqld/ha_blackhole.cc +++ /dev/null diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 56f4200e695..a2c570c2fbc 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -28,10 +28,6 @@ extern "C" extern unsigned long max_allowed_packet, net_buffer_length; } -static int fake_argc= 1; -static char *fake_argv[]= {(char *)"", 0}; -static const char *fake_groups[] = { "server", "embedded", 0 }; - #if defined (__WIN__) #include "../sql/mysqld.cpp" #else @@ -44,25 +40,40 @@ int check_user(THD *thd, enum enum_server_command command, void thd_init_client_charset(THD *thd, uint cs_number); C_MODE_START + #include <mysql.h> #undef ER #include "errmsg.h" #include <sql_common.h> +#include "embedded_priv.h" + +static my_bool emb_read_query_result(MYSQL *mysql); + + +/* + Reads error information from the MYSQL_DATA and puts + it into proper MYSQL members + + SYNOPSIS + embedded_get_error() + mysql connection handler + data query result + + NOTES + after that function error information will be accessible + with usual functions like mysql_error() + data is my_free-d in this function + most of the data is stored in data->embedded_info structure +*/ -void embedded_get_error(MYSQL *mysql) +void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data) { - THD *thd=(THD *) mysql->thd; NET *net= &mysql->net; - if ((net->last_errno= thd->net.last_errno)) - { - memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error)); - memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate)); - } - else - { - net->last_error[0]= 0; - strmov(net->sqlstate, not_error_sqlstate); - } + struct embedded_query_result *ei= data->embedded_info; + net->last_errno= ei->last_errno; + strmake(net->last_error, ei->info, sizeof(net->last_error)); + memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate)); + my_free((gptr) data, MYF(0)); } static my_bool @@ -74,11 +85,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, THD *thd=(THD *) mysql->thd; NET *net= &mysql->net; - if (thd->data) - { - free_rows(thd->data); - thd->data= 0; - } + thd->clear_data_list(); /* Check that we are calling the client functions in right order */ if (mysql->status != MYSQL_STATUS_READY) { @@ -110,83 +117,101 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, arg_length= header_length; } + thd->net.no_send_error= 0; result= dispatch_command(command, thd, (char *) arg, arg_length + 1); + thd->cur_data= 0; if (!skip_check) result= thd->net.last_errno ? -1 : 0; - /* - If mysql->field_count is set it means the parsing of the query was OK - and metadata was returned (see Protocol::send_fields). - In this case we postpone the error to be returned in mysql_stmt_store_result - (see emb_read_rows) to behave just as standalone server. - */ - if (!mysql->field_count) - embedded_get_error(mysql); - mysql->server_status= thd->server_status; - mysql->warning_count= ((THD*)mysql->thd)->total_warn_count; return result; } static void emb_flush_use_result(MYSQL *mysql) { - MYSQL_DATA *data= ((THD*)(mysql->thd))->data; - - if (data) + THD *thd= (THD*) mysql->thd; + if (thd->cur_data) { + free_rows(thd->cur_data); + thd->cur_data= 0; + } + else if (thd->first_data) + { + MYSQL_DATA *data= thd->first_data; + thd->first_data= data->embedded_info->next; free_rows(data); - ((THD*)(mysql->thd))->data= NULL; } } + +/* + reads dataset from the next query result + + SYNOPSIS + emb_read_rows() + mysql connection handle + other parameters are not used + + NOTES + It just gets next MYSQL_DATA from the result's queue + + RETURN + pointer to MYSQL_DATA with the coming recordset +*/ + static MYSQL_DATA * emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)), unsigned int fields __attribute__((unused))) { - MYSQL_DATA *result= ((THD*)mysql->thd)->data; - embedded_get_error(mysql); - if (mysql->net.last_errno) - return NULL; - if (!result) + MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data; + ((THD*)mysql->thd)->cur_data= 0; + if (result->embedded_info->last_errno) { - if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - { - NET *net = &mysql->net; - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); - return NULL; - } - return result; - } - *result->prev_ptr= NULL; - ((THD*)mysql->thd)->data= NULL; + embedded_get_error(mysql, result); + return NULL; + } + *result->embedded_info->prev_ptr= NULL; return result; } + static MYSQL_FIELD *emb_list_fields(MYSQL *mysql) { + MYSQL_DATA *res; + if (emb_read_query_result(mysql)) + return 0; + res= ((THD*) mysql->thd)->cur_data; + ((THD*) mysql->thd)->cur_data= 0; + mysql->field_alloc= res->alloc; + my_free((gptr) res,MYF(0)); + mysql->status= MYSQL_STATUS_READY; return mysql->fields; } static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) { - THD *thd= (THD*)mysql->thd; - if (mysql->net.last_errno) - return 1; + THD *thd= (THD*) mysql->thd; + MYSQL_DATA *res; + stmt->stmt_id= thd->client_stmt_id; stmt->param_count= thd->client_param_count; - stmt->field_count= mysql->field_count; + stmt->field_count= 0; - if (stmt->field_count != 0) + if (thd->first_data) { + if (emb_read_query_result(mysql)) + return 1; + stmt->field_count= mysql->field_count; + mysql->status= MYSQL_STATUS_READY; + res= thd->cur_data; + thd->cur_data= NULL; if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) mysql->server_status|= SERVER_STATUS_IN_TRANS; stmt->fields= mysql->fields; - stmt->mem_root= mysql->field_alloc; + stmt->mem_root= res->alloc; mysql->fields= NULL; + my_free((gptr) res,MYF(0)); } return 0; @@ -207,13 +232,42 @@ static void emb_fetch_lengths(ulong *to, MYSQL_ROW column, *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0; } -static my_bool emb_mysql_read_query_result(MYSQL *mysql) +static my_bool emb_read_query_result(MYSQL *mysql) { - if (mysql->net.last_errno) - return -1; + THD *thd= (THD*) mysql->thd; + MYSQL_DATA *res= thd->first_data; + DBUG_ASSERT(!thd->cur_data); + thd->first_data= res->embedded_info->next; + if (res->embedded_info->last_errno && + !res->embedded_info->fields_list) + { + embedded_get_error(mysql, res); + return 1; + } - if (mysql->field_count) + mysql->warning_count= res->embedded_info->warning_count; + mysql->server_status= res->embedded_info->server_status; + mysql->field_count= res->fields; + mysql->fields= res->embedded_info->fields_list; + mysql->affected_rows= res->embedded_info->affected_rows; + mysql->insert_id= res->embedded_info->insert_id; + mysql->net.last_errno= 0; + mysql->net.last_error[0]= 0; + mysql->info= 0; + + if (res->embedded_info->info[0]) + { + strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1); + mysql->info= mysql->info_buffer; + } + + if (res->embedded_info->fields_list) + { mysql->status=MYSQL_STATUS_GET_RESULT; + thd->cur_data= res; + } + else + my_free((gptr) res, MYF(0)); return 0; } @@ -221,14 +275,18 @@ static my_bool emb_mysql_read_query_result(MYSQL *mysql) static int emb_stmt_execute(MYSQL_STMT *stmt) { DBUG_ENTER("emb_stmt_execute"); - char header[4]; + char header[5]; + MYSQL_DATA *res; + THD *thd; + int4store(header, stmt->stmt_id); - THD *thd= (THD*)stmt->mysql->thd; + header[4]= stmt->flags; + thd= (THD*)stmt->mysql->thd; thd->client_param_count= stmt->param_count; thd->client_params= stmt->params; - if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0, + if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0, header, sizeof(header), 1) || - emb_mysql_read_query_result(stmt->mysql)) + emb_read_query_result(stmt->mysql)) { NET *net= &stmt->mysql->net; set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); @@ -236,6 +294,8 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) } stmt->affected_rows= stmt->mysql->affected_rows; stmt->insert_id= stmt->mysql->insert_id; + stmt->server_status= stmt->mysql->server_status; + DBUG_RETURN(0); } @@ -246,22 +306,53 @@ int emb_read_binary_rows(MYSQL_STMT *stmt) return 1; stmt->result= *data; my_free((char *) data, MYF(0)); + set_stmt_errmsg(stmt, stmt->mysql->net.last_error, + stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate); return 0; } +int emb_read_rows_from_cursor(MYSQL_STMT *stmt) +{ + MYSQL *mysql= stmt->mysql; + THD *thd= (THD*) mysql->thd; + MYSQL_DATA *res= thd->first_data; + DBUG_ASSERT(!thd->first_data->embedded_info->next); + thd->first_data= 0; + if (res->embedded_info->last_errno) + { + embedded_get_error(mysql, res); + set_stmt_errmsg(stmt, mysql->net.last_error, + mysql->net.last_errno, mysql->net.sqlstate); + return 1; + } + + thd->cur_data= res; + mysql->warning_count= res->embedded_info->warning_count; + mysql->server_status= res->embedded_info->server_status; + mysql->net.last_errno= 0; + mysql->net.last_error[0]= 0; + + return emb_read_binary_rows(stmt); +} + int emb_unbuffered_fetch(MYSQL *mysql, char **row) { - MYSQL_DATA *data= ((THD*)mysql->thd)->data; - embedded_get_error(mysql); - if (mysql->net.last_errno) - return mysql->net.last_errno; + THD *thd= (THD*) mysql->thd; + MYSQL_DATA *data= thd->cur_data; + if (data && data->embedded_info->last_errno) + { + embedded_get_error(mysql, data); + thd->cur_data= 0; + return 1; + } if (!data || !data->data) { *row= NULL; if (data) { + thd->cur_data= thd->first_data; + thd->first_data= data->embedded_info->next; free_rows(data); - ((THD*)mysql->thd)->data= NULL; } } else @@ -275,9 +366,9 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row) static void emb_free_embedded_thd(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; - if (thd->data) - free_rows(thd->data); + thd->clear_data_list(); thread_count--; + thd->store_globals(); delete thd; mysql->thd=0; } @@ -289,23 +380,11 @@ static const char * emb_read_statistics(MYSQL *mysql) } -static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql) +static MYSQL_RES * emb_store_result(MYSQL *mysql) { return mysql_store_result(mysql); } -my_bool emb_next_result(MYSQL *mysql) -{ - THD *thd= (THD*)mysql->thd; - DBUG_ENTER("emb_next_result"); - - if (emb_advanced_command(mysql, COM_QUERY,0,0, - thd->query_rest.ptr(),thd->query_rest.length(),1) || - emb_mysql_read_query_result(mysql)) - DBUG_RETURN(1); - - DBUG_RETURN(0); /* No more results */ -} int emb_read_change_user_result(MYSQL *mysql, char *buff __attribute__((unused)), @@ -316,10 +395,10 @@ int emb_read_change_user_result(MYSQL *mysql, MYSQL_METHODS embedded_methods= { - emb_mysql_read_query_result, + emb_read_query_result, emb_advanced_command, emb_read_rows, - emb_mysql_store_result, + emb_store_result, emb_fetch_lengths, emb_flush_use_result, emb_list_fields, @@ -329,19 +408,11 @@ MYSQL_METHODS embedded_methods= emb_unbuffered_fetch, emb_free_embedded_thd, emb_read_statistics, - emb_next_result, - emb_read_change_user_result + emb_read_query_result, + emb_read_change_user_result, + emb_read_rows_from_cursor }; -C_MODE_END - -void THD::clear_error() -{ - net.last_error[0]= 0; - net.last_errno= 0; - net.report_error= 0; -} - /* Make a copy of array and the strings array points to */ @@ -368,11 +439,7 @@ char **copy_arguments(int argc, char **argv) return res; } - -extern "C" -{ - -char ** copy_arguments_ptr= 0; +char ** copy_arguments_ptr= 0; int init_embedded_server(int argc, char **argv, char **groups) { @@ -481,14 +548,13 @@ void end_embedded_server() clean_up(0); } -} /* extern "C" */ -C_MODE_START void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db) { THD *thd = (THD *)mysql->thd; thd->mysql= mysql; mysql->server_version= server_version; + init_alloc_root(&mysql->field_alloc, 8192, 0); } void *create_embedded_thd(int client_flag, char *db) @@ -496,6 +562,7 @@ void *create_embedded_thd(int client_flag, char *db) THD * thd= new THD; thd->thread_id= thread_id++; + thd->thread_stack= (char*) &thd; if (thd->store_globals()) { fprintf(stderr,"store_globals failed.\n"); @@ -520,12 +587,13 @@ void *create_embedded_thd(int client_flag, char *db) thd->db= db; thd->db_length= db ? strip_sp(db) : 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS - thd->db_access= DB_ACLS; - thd->master_access= ~NO_ACCESS; + thd->security_ctx->db_access= DB_ACLS; + thd->security_ctx->master_access= ~NO_ACCESS; #endif - thd->net.query_cache_query= 0; - - thd->data= 0; + thd->cur_data= 0; + thd->first_data= 0; + thd->data_tail= &thd->first_data; + bzero((char*) &thd->net, sizeof(thd->net)); thread_count++; return thd; @@ -538,20 +606,24 @@ err: #ifdef NO_EMBEDDED_ACCESS_CHECKS int check_embedded_connection(MYSQL *mysql) { + int result; THD *thd= (THD*)mysql->thd; thd_init_client_charset(thd, mysql->charset->number); thd->update_charset(); - thd->host= (char*)my_localhost; - thd->host_or_ip= thd->host; - thd->user= my_strdup(mysql->user, MYF(0)); - thd->priv_user= thd->user; - return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true); + Security_context *sctx= thd->security_ctx; + sctx->host_or_ip= sctx->host= (char*) my_localhost; + strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1); + sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0)); + result= check_user(thd, COM_CONNECT, NULL, 0, thd->db, true); + emb_read_query_result(mysql); + return result; } #else int check_embedded_connection(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; + Security_context *sctx= thd->security_ctx; int result; char scramble_buff[SCRAMBLE_LENGTH]; int passwd_len; @@ -560,20 +632,20 @@ int check_embedded_connection(MYSQL *mysql) thd->update_charset(); if (mysql->options.client_ip) { - thd->host= my_strdup(mysql->options.client_ip, MYF(0)); - thd->ip= my_strdup(thd->host, MYF(0)); + sctx->host= my_strdup(mysql->options.client_ip, MYF(0)); + sctx->ip= my_strdup(sctx->host, MYF(0)); } else - thd->host= (char*)my_localhost; - thd->host_or_ip= thd->host; + sctx->host= (char*)my_localhost; + sctx->host_or_ip= sctx->host; - if (acl_check_host(thd->host,thd->ip)) + if (acl_check_host(sctx->host, sctx->ip)) { result= ER_HOST_NOT_PRIVILEGED; goto err; } - thd->user= my_strdup(mysql->user, MYF(0)); + sctx->user= my_strdup(mysql->user, MYF(0)); if (mysql->passwd && mysql->passwd[0]) { memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble @@ -601,6 +673,26 @@ err: C_MODE_END +void THD::clear_data_list() +{ + while (first_data) + { + MYSQL_DATA *data= first_data; + first_data= data->embedded_info->next; + free_rows(data); + } + data_tail= &first_data; + free_rows(cur_data); + cur_data= 0; +} + +void THD::clear_error() +{ + net.last_error[0]= 0; + net.last_errno= 0; + net.report_error= 0; +} + static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { @@ -627,26 +719,147 @@ static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, } -bool Protocol::send_fields(List<Item> *list, uint flag) +/* + creates new result and hooks it to the list + + SYNOPSIS + alloc_new_dataset() + + NOTES + allocs the MYSQL_DATA + embedded_query_result couple + to store the next query result, + links these two and attach it to the THD::data_tail + + RETURN + pointer to the newly created query result +*/ + +MYSQL_DATA *THD::alloc_new_dataset() +{ + MYSQL_DATA *data; + struct embedded_query_result *emb_data; + if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &data, sizeof(*data), + &emb_data, sizeof(*emb_data), + NULL)) + return NULL; + + emb_data->prev_ptr= &data->data; + cur_data= data; + *data_tail= data; + data_tail= &emb_data->next; + data->embedded_info= emb_data; + return data; +} + + +/* + stores server_status and warning_count in the current + query result structures + + SYNOPSIS + write_eof_packet() + thd current thread + + NOTES + should be called to after we get the recordset-result + +*/ + +static void write_eof_packet(THD *thd) +{ + /* + The following test should never be true, but it's better to do it + because if 'is_fatal_error' is set the server is not going to execute + other queries (see the if test in dispatch_command / COM_QUERY) + */ + if (thd->is_fatal_error) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + thd->cur_data->embedded_info->server_status= thd->server_status; + /* + Don't send warn count during SP execution, as the warn_list + is cleared between substatements, and mysqltest gets confused + */ + thd->cur_data->embedded_info->warning_count= + (thd->spcont ? 0 : min(thd->total_warn_count, 65535)); +} + + +/* + allocs new query result and initialises Protocol::alloc + + SYNOPSIS + Protocol::begin_dataset() + + RETURN + 0 if success + 1 if memory allocation failed +*/ + +int Protocol::begin_dataset() +{ + MYSQL_DATA *data= thd->alloc_new_dataset(); + if (!data) + return 1; + alloc= &data->alloc; + init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */ + alloc->min_malloc=sizeof(MYSQL_ROWS); + return 0; +} + + +/* + remove last row of current recordset + + SYNOPSIS + Protocol_simple::remove_last_row() + + NOTES + does the loop from the beginning of the current recordset to + the last record and cuts it off. + Not supposed to be frequently called. +*/ + +void Protocol_simple::remove_last_row() +{ + MYSQL_DATA *data= thd->cur_data; + MYSQL_ROWS **last_row_hook= &data->data; + uint count= data->rows; + DBUG_ENTER("Protocol_simple::remove_last_row"); + while (--count) + last_row_hook= &(*last_row_hook)->next; + + *last_row_hook= 0; + data->embedded_info->prev_ptr= last_row_hook; + data->rows--; + + DBUG_VOID_RETURN; +} + + +bool Protocol::send_fields(List<Item> *list, uint flags) { List_iterator_fast<Item> it(*list); Item *item; MYSQL_FIELD *client_field; - MYSQL *mysql= thd->mysql; MEM_ROOT *field_alloc; CHARSET_INFO *thd_cs= thd->variables.character_set_results; CHARSET_INFO *cs= system_charset_info; - + MYSQL_DATA *data; DBUG_ENTER("send_fields"); - if (!mysql) // bootstrap file handling + if (!thd->mysql) // bootstrap file handling DBUG_RETURN(0); - field_count= list->elements; - field_alloc= &mysql->field_alloc; - if (!(client_field= thd->mysql->fields= - (MYSQL_FIELD *)alloc_root(field_alloc, - sizeof(MYSQL_FIELD) * field_count))) + if (begin_dataset()) + goto err; + + data= thd->cur_data; + data->fields= field_count= list->elements; + field_alloc= &data->alloc; + + if (!(client_field= data->embedded_info->fields_list= + (MYSQL_FIELD*)alloc_root(field_alloc, sizeof(MYSQL_FIELD)*field_count))) goto err; while ((item= it++)) @@ -654,6 +867,10 @@ bool Protocol::send_fields(List<Item> *list, uint flag) Send_field server_field; item->make_field(&server_field); + /* Keep things compatible for old clients */ + if (server_field.type == MYSQL_TYPE_VARCHAR) + server_field.type= MYSQL_TYPE_VAR_STRING; + client_field->db= dup_str_aux(field_alloc, server_field.db_name, strlen(server_field.db_name), cs, thd_cs); client_field->table= dup_str_aux(field_alloc, server_field.table_name, @@ -692,7 +909,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) if (INTERNAL_NUM_FIELD(client_field)) client_field->flags|= NUM_FLAG; - if (flag & 2) + if (flags & (int) Protocol::SEND_DEFAULTS) { char buff[80]; String tmp(buff, sizeof(buff), default_charset_info), *res; @@ -714,19 +931,16 @@ bool Protocol::send_fields(List<Item> *list, uint flag) client_field->max_length= 0; ++client_field; } - thd->mysql->field_count= field_count; + + if (flags & SEND_EOF) + write_eof_packet(thd); DBUG_RETURN(prepare_for_send(list)); err: - send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */ + my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } -bool Protocol::send_records_num(List<Item> *list, ulonglong records) -{ - return false; -} - bool Protocol::write() { if (!thd->mysql) // bootstrap file handling @@ -739,25 +953,11 @@ bool Protocol::write() bool Protocol_prep::write() { MYSQL_ROWS *cur; - MYSQL_DATA *data= thd->data; - - if (!data) - { - if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - return true; - - alloc= &data->alloc; - init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */ - alloc->min_malloc=sizeof(MYSQL_ROWS); - data->rows=0; - data->fields=field_count; - data->prev_ptr= &data->data; - thd->data= data; - } + MYSQL_DATA *data= thd->cur_data; data->rows++; - if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+packet->length()))) + if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, + sizeof(MYSQL_ROWS)+packet->length()))) { my_error(ER_OUT_OF_RESOURCES,MYF(0)); return true; @@ -766,8 +966,8 @@ bool Protocol_prep::write() memcpy(cur->data, packet->ptr()+1, packet->length()-1); cur->length= packet->length(); /* To allow us to do sanity checks */ - *data->prev_ptr= cur; - data->prev_ptr= &cur->next; + *data->embedded_info->prev_ptr= cur; + data->embedded_info->prev_ptr= &cur->next; cur->next= 0; return false; @@ -777,46 +977,52 @@ void send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) { DBUG_ENTER("send_ok"); - MYSQL *mysql= current_thd->mysql; + MYSQL_DATA *data; + MYSQL *mysql= thd->mysql; + if (!mysql) // bootstrap file handling DBUG_VOID_RETURN; - mysql->affected_rows= affected_rows; - mysql->insert_id= id; + if (thd->net.no_send_ok) // hack for re-parsing queries + DBUG_VOID_RETURN; + if (!(data= thd->alloc_new_dataset())) + return; + data->embedded_info->affected_rows= affected_rows; + data->embedded_info->insert_id= id; if (message) - { - strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1); - mysql->info= thd->net.last_error; - } + strmake(data->embedded_info->info, message, + sizeof(data->embedded_info->info)-1); + + write_eof_packet(thd); + thd->cur_data= 0; DBUG_VOID_RETURN; } void -send_eof(THD *thd, bool no_flush) +send_eof(THD *thd) +{ + write_eof_packet(thd); + thd->cur_data= 0; +} + + +void net_send_error_packet(THD *thd, uint sql_errno, const char *err) { + MYSQL_DATA *data= thd->cur_data ? thd->cur_data : thd->alloc_new_dataset(); + struct embedded_query_result *ei= data->embedded_info; + + ei->last_errno= sql_errno; + strmake(ei->info, err, sizeof(ei->info)-1); + strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno)); + thd->cur_data= 0; } + void Protocol_simple::prepare_for_resend() { MYSQL_ROWS *cur; - MYSQL_DATA *data= thd->data; - + MYSQL_DATA *data= thd->cur_data; DBUG_ENTER("send_data"); - if (!data) - { - if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - goto err; - - alloc= &data->alloc; - init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */ - alloc->min_malloc=sizeof(MYSQL_ROWS); - data->rows=0; - data->fields=field_count; - data->prev_ptr= &data->data; - thd->data= data; - } - data->rows++; if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) { @@ -825,10 +1031,10 @@ void Protocol_simple::prepare_for_resend() } cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); - *data->prev_ptr= cur; - data->prev_ptr= &cur->next; + *data->embedded_info->prev_ptr= cur; + data->embedded_info->prev_ptr= &cur->next; next_field=cur->data; - next_mysql_field= thd->mysql->fields; + next_mysql_field= data->embedded_info->fields_list; err: DBUG_VOID_RETURN; } diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index a2bd4242c3d..5df61783451 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -14,6 +14,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <my_global.h> +#include <mysql.h> +#include <mysql_embed.h> +#include <mysqld_error.h> +#include <my_pthread.h> #include "embedded_priv.h" #include <my_sys.h> #include <mysys_err.h> @@ -151,12 +156,26 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (!user) user= ""; - mysql->user=my_strdup(user,MYF(0)); + /* + We need to alloc some space for mysql->info but don't want to + put extra 'my_free's in mysql_close. + So we alloc it with the 'user' string to be freed at once + */ + mysql->user= my_strdup(user, MYF(0)); port=0; unix_socket=0; db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL; + /* Send client information for access check */ + client_flag|=CLIENT_CAPABILITIES; + if (client_flag & CLIENT_MULTI_STATEMENTS) + client_flag|= CLIENT_MULTI_RESULTS; + client_flag&= ~CLIENT_COMPRESS; + if (db) + client_flag|=CLIENT_CONNECT_WITH_DB; + + mysql->info_buffer= my_malloc(MYSQL_ERRMSG_SIZE, MYF(0)); mysql->thd= create_embedded_thd(client_flag, db_name); init_embedded_mysql(mysql, client_flag, db_name); @@ -167,11 +186,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (check_embedded_connection(mysql)) goto error; - /* Send client information for access check */ - client_flag|=CLIENT_CAPABILITIES; - client_flag&= ~CLIENT_COMPRESS; - if (db) - client_flag|=CLIENT_CONNECT_WITH_DB; mysql->server_status= SERVER_STATUS_AUTOCOMMIT; if (mysql->options.init_commands) @@ -198,7 +212,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_RETURN(mysql); error: - embedded_get_error(mysql); DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno, mysql->net.last_error)); { diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index ea3133594f5..3895588e02c 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -1,6 +1,6 @@ LIBRARY LIBMYSQLD -DESCRIPTION 'MySQL 4.1 Embedded Server Library' -VERSION 4.1 +DESCRIPTION 'MySQL 5.0 Embedded Server Library' +VERSION 5.0 EXPORTS _dig_vec_upper _dig_vec_lower @@ -58,6 +58,7 @@ EXPORTS mysql_get_host_info mysql_get_proto_info mysql_get_server_info + mysql_get_ssl_cipher mysql_info mysql_init mysql_insert_id @@ -113,6 +114,7 @@ EXPORTS my_charset_latin1 init_alloc_root my_progname + get_charset_name get_charset_by_csname print_defaults find_type @@ -157,4 +159,7 @@ EXPORTS mysql_stmt_attr_get mysql_stmt_attr_set mysql_stmt_field_count - get_defaults_files + get_defaults_options + my_charset_bin + my_charset_same + modify_defaults_file diff --git a/libmysqld/libmysqld.rc b/libmysqld/libmysqld.rc index 5b6142faddf..5b6142faddf 100755..100644 --- a/libmysqld/libmysqld.rc +++ b/libmysqld/libmysqld.rc diff --git a/libmysqld/resource.h b/libmysqld/resource.h index f770fe490a6..f770fe490a6 100755..100644 --- a/libmysqld/resource.h +++ b/libmysqld/resource.h |