diff options
Diffstat (limited to 'libmysqld')
-rw-r--r-- | libmysqld/CMakeLists.txt | 2 | ||||
-rw-r--r-- | libmysqld/Makefile.am | 1 | ||||
-rw-r--r-- | libmysqld/emb_qcache.cc | 105 | ||||
-rw-r--r-- | libmysqld/emb_qcache.h | 5 | ||||
-rw-r--r-- | libmysqld/lib_sql.cc | 131 | ||||
-rw-r--r-- | libmysqld/libmysqld.c | 5 | ||||
-rw-r--r-- | libmysqld/libmysqld.def | 1 |
7 files changed, 160 insertions, 90 deletions
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index fb3316c303c..9fa7d46d466 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -22,7 +22,7 @@ IF(WIN32) ADD_DEFINITIONS(-DUSE_TLS) ENDIF(WIN32) -ADD_DEFINITIONS(-DMYSQL_SERVER -DEMBEDDED_LIBRARY) +ADD_DEFINITIONS(-DMYSQL_SERVER -DEMBEDDED_LIBRARY -DHAVE_DLOPEN) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/libmysqld diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index c0784447216..5d673bb340e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -59,6 +59,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ protocol.cc net_serv.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ sql_load.cc discover.cc sql_locale.cc \ + sql_profile.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \ diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc index 17549bfa96b..fdd7f8ed776 100644 --- a/libmysqld/emb_qcache.cc +++ b/libmysqld/emb_qcache.cc @@ -19,7 +19,7 @@ #include "emb_qcache.h" #include "embedded_priv.h" -void Querycache_stream::store_char(char c) +void Querycache_stream::store_uchar(uchar c) { if (data_end == cur_data) use_next_block(TRUE); @@ -142,7 +142,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len) store_int(0); } -char Querycache_stream::load_char() +uchar Querycache_stream::load_uchar() { if (cur_data == data_end) use_next_block(FALSE); @@ -301,8 +301,8 @@ uint emb_count_querycache_size(THD *thd) *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); + /* n_fields + n_rows + field_info * n_fields */ + result+= (uint) (4+8 + 42*data->fields); for(; field < field_end; field++) { @@ -313,13 +313,23 @@ uint emb_count_querycache_size(THD *thd) result+= field->def_length; } - for (; cur_row; cur_row=cur_row->next) + if (thd->protocol == &thd->protocol_binary) { - MYSQL_ROW col= cur_row->data; - MYSQL_ROW col_end= col + data->fields; - for (; col < col_end; col++) - if (*col) - result+= *(uint *)((*col) - sizeof(uint)); + result+= (uint) (4*n_rows); + for (; cur_row; cur_row=cur_row->next) + result+= cur_row->length; + } + else + { + result+= (uint) (4*n_rows*data->fields); + for (; cur_row; cur_row=cur_row->next) + { + MYSQL_ROW col= cur_row->data; + MYSQL_ROW col_end= col + data->fields; + for (; col < col_end; col++) + if (*col) + result+= *(uint *)((*col) - sizeof(uint)); + } } return result; } @@ -353,10 +363,10 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) { dst->store_int((uint)field->length); dst->store_int((uint)field->max_length); - dst->store_char((char)field->type); + dst->store_uchar((uchar)field->type); dst->store_short((ushort)field->flags); dst->store_short((ushort)field->charsetnr); - dst->store_char((char)field->decimals); + dst->store_uchar((uchar)field->decimals); dst->store_str(field->name, field->name_length); dst->store_str(field->table, field->table_length); dst->store_str(field->org_name, field->org_name_length); @@ -366,14 +376,22 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) dst->store_safe_str(field->def, field->def_length); } - for (; cur_row; cur_row=cur_row->next) + if (thd->protocol == &thd->protocol_binary) { - MYSQL_ROW col= cur_row->data; - MYSQL_ROW col_end= col + data->fields; - for (; col < col_end; col++) + for (; cur_row; cur_row=cur_row->next) + dst->store_str((char *) cur_row->data, cur_row->length); + } + else + { + for (; cur_row; cur_row=cur_row->next) { - uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; - dst->store_safe_str(*col, len); + MYSQL_ROW col= cur_row->data; + MYSQL_ROW col_end= col + data->fields; + for (; col < col_end; col++) + { + uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; + dst->store_safe_str(*col, len); + } } } DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size); @@ -408,10 +426,10 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) { field->length= src->load_int(); field->max_length= (unsigned int)src->load_int(); - field->type= (enum enum_field_types)src->load_char(); + field->type= (enum enum_field_types)src->load_uchar(); field->flags= (unsigned int)src->load_short(); field->charsetnr= (unsigned int)src->load_short(); - field->decimals= (unsigned int)src->load_char(); + field->decimals= src->load_uchar(); if (!(field->name= src->load_str(f_alloc, &field->name_length)) || !(field->table= src->load_str(f_alloc,&field->table_length)) || @@ -423,31 +441,48 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) goto err; } - 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->data= row; if (!rows) goto return_ok; + if (thd->protocol == &thd->protocol_binary) + { + uint length; + row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS)); + end_row= row + rows; + data->data= row; - for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) + for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) + { + *prev_row= row; + row->data= (MYSQL_ROW) src->load_str(&data->alloc, &length); + row->length= length; + } + } + else { - *prev_row= row; - row->data= columns; - MYSQL_ROW col_end= columns + data->fields; - for (; columns < col_end; columns++) - src->load_column(&data->alloc, columns); + 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; - *(columns++)= NULL; + data->data= row; + + for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) + { + *prev_row= row; + row->data= columns; + MYSQL_ROW col_end= columns + data->fields; + for (; columns < col_end; columns++) + src->load_column(&data->alloc, columns); + + *(columns++)= NULL; + } } *prev_row= NULL; data->embedded_info->prev_ptr= prev_row; return_ok: - send_eof(thd); + net_send_eof(thd, thd->server_status, thd->total_warn_count); DBUG_RETURN(0); err: DBUG_RETURN(1); diff --git a/libmysqld/emb_qcache.h b/libmysqld/emb_qcache.h index 6e320fbd967..67413739f2c 100644 --- a/libmysqld/emb_qcache.h +++ b/libmysqld/emb_qcache.h @@ -58,7 +58,7 @@ public: data_end= cur_data + (block->used-headers_len); } - void store_char(char c); + void store_uchar(uchar c); void store_short(ushort s); void store_int(uint i); void store_ll(ulonglong ll); @@ -66,7 +66,7 @@ public: void store_str(const char *str, uint str_len); void store_safe_str(const char *str, uint str_len); - char load_char(); + uchar load_uchar(); ushort load_short(); uint load_int(); ulonglong load_ll(); @@ -79,3 +79,4 @@ public: uint emb_count_querycache_size(THD *thd); int emb_load_querycache_result(THD *thd, Querycache_stream *src); void emb_store_querycache_result(Querycache_stream *dst, THD* thd); +void net_send_eof(THD *thd, uint server_status, uint total_warn_count); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 4e525f8447f..cb3b6a7115d 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -61,9 +61,10 @@ void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data) { NET *net= &mysql->net; struct embedded_query_result *ei= data->embedded_info; - net->last_errno= ei->last_errno; - strmake(net->last_error, ei->info, sizeof(net->last_error)); + net->client_last_errno= ei->last_errno; + strmake(net->client_last_error, ei->info, sizeof(net->client_last_error)-1); memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate)); + mysql->server_status= ei->server_status; my_free(data, MYF(0)); } @@ -77,23 +78,28 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, THD *thd=(THD *) mysql->thd; NET *net= &mysql->net; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.start_new_query(); +#endif + thd->clear_data_list(); /* Check that we are calling the client functions in right order */ if (mysql->status != MYSQL_STATUS_READY) { - strmov(net->last_error, - ER(net->last_errno=CR_COMMANDS_OUT_OF_SYNC)); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); return 1; } /* Clear result variables */ thd->clear_error(); + thd->main_da.reset_diagnostics_area(); mysql->affected_rows= ~(my_ulonglong) 0; mysql->field_count= 0; - net->last_errno= 0; + net_clear_error(net); thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect + lex_start(thd); /* We have to call free_old_query before we start to fill mysql->fields for new query. In the case of embedded server we collect field data @@ -110,13 +116,15 @@ 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); thd->cur_data= 0; if (!skip_check) - result= thd->net.last_errno ? -1 : 0; + result= thd->is_error() ? -1 : 0; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.finish_current_query(); +#endif return result; } @@ -242,11 +250,12 @@ static my_bool emb_read_query_result(MYSQL *mysql) 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; + if (!(mysql->fields= res->embedded_info->fields_list)) + { + mysql->affected_rows= res->embedded_info->affected_rows; + mysql->insert_id= res->embedded_info->insert_id; + } + net_clear_error(&mysql->net); mysql->info= 0; if (res->embedded_info->info[0]) @@ -288,7 +297,7 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) if (res) { NET *net= &stmt->mysql->net; - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -299,14 +308,12 @@ int emb_read_binary_rows(MYSQL_STMT *stmt) MYSQL_DATA *data; if (!(data= emb_read_rows(stmt->mysql, 0, 0))) { - set_stmt_errmsg(stmt, stmt->mysql->net.last_error, - stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate); + set_stmt_errmsg(stmt, &stmt->mysql->net); 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); + set_stmt_errmsg(stmt, &stmt->mysql->net); return 0; } @@ -320,16 +327,14 @@ int emb_read_rows_from_cursor(MYSQL_STMT *stmt) 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); + set_stmt_errmsg(stmt, &mysql->net); 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; + net_clear_error(&mysql->net); return emb_read_binary_rows(stmt); } @@ -375,7 +380,7 @@ static void emb_free_embedded_thd(MYSQL *mysql) static const char * emb_read_statistics(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; - return thd->net.last_error; + return thd->is_error() ? thd->main_da.message() : ""; } @@ -551,7 +556,6 @@ void end_embedded_server() { my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; - release_ddl_log(); clean_up(0); } @@ -586,6 +590,7 @@ void *create_embedded_thd(int client_flag) fprintf(stderr,"store_globals failed.\n"); goto err; } + lex_start(thd); /* TODO - add init_connect command execution */ @@ -630,6 +635,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db) 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, db, true); + net_end_statement(thd); emb_read_query_result(mysql); return result; } @@ -679,8 +685,10 @@ int check_embedded_connection(MYSQL *mysql, const char *db) err: { NET *net= &mysql->net; - memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error)); - memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate)); + strmake(net->client_last_error, thd->main_da.message(), sizeof(net->client_last_error)-1); + memcpy(net->sqlstate, + mysql_errno_to_sqlstate(thd->main_da.sql_errno()), + sizeof(net->sqlstate)-1); } return result; } @@ -703,9 +711,8 @@ void THD::clear_data_list() void THD::clear_error() { - net.last_error[0]= 0; - net.last_errno= 0; - net.report_error= 0; + if (main_da.is_error()) + main_da.reset_diagnostics_area(); } static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, @@ -768,20 +775,18 @@ MYSQL_DATA *THD::alloc_new_dataset() } -/* - stores server_status and warning_count in the current - query result structures - - SYNOPSIS - write_eof_packet() - thd current thread +/** + Stores server_status and warning_count in the current + query result structures. - NOTES - should be called to after we get the recordset-result + @param thd current thread + @note Should be called after we get the recordset-result. */ -static void write_eof_packet(THD *thd) +static +void +write_eof_packet(THD *thd, uint server_status, uint total_warn_count) { if (!thd->mysql) // bootstrap file handling return; @@ -792,13 +797,13 @@ static void write_eof_packet(THD *thd) */ if (thd->is_fatal_error) thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; - thd->cur_data->embedded_info->server_status= thd->server_status; + thd->cur_data->embedded_info->server_status= 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)); + (thd->spcont ? 0 : min(total_warn_count, 65535)); } @@ -954,7 +959,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) } if (flags & SEND_EOF) - write_eof_packet(thd); + write_eof_packet(thd, thd->server_status, thd->total_warn_count); DBUG_RETURN(prepare_for_send(list)); err: @@ -994,17 +999,35 @@ bool Protocol_binary::write() return false; } + +/** + Embedded library implementation of OK response. + + This function is used by the server to write 'OK' packet to + the "network" when the server is compiled as an embedded library. + Since there is no network in the embedded configuration, + a different implementation is necessary. + Instead of marshalling response parameters to a network representation + and then writing it to the socket, here we simply copy the data to the + corresponding client-side connection structures. + + @sa Server implementation of net_send_ok in protocol.cc for + description of the arguments. + + @return The function does not return errors. +*/ + void -send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) +net_send_ok(THD *thd, + uint server_status, uint total_warn_count, + ha_rows affected_rows, ulonglong id, const char *message) { - DBUG_ENTER("send_ok"); + DBUG_ENTER("emb_net_send_ok"); MYSQL_DATA *data; MYSQL *mysql= thd->mysql; - + if (!mysql) // bootstrap file handling DBUG_VOID_RETURN; - 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; @@ -1013,15 +1036,24 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) strmake(data->embedded_info->info, message, sizeof(data->embedded_info->info)-1); - write_eof_packet(thd); + write_eof_packet(thd, server_status, total_warn_count); thd->cur_data= 0; DBUG_VOID_RETURN; } + +/** + Embedded library implementation of EOF response. + + @sa net_send_ok + + @return This function does not return errors. +*/ + void -send_eof(THD *thd) +net_send_eof(THD *thd, uint server_status, uint total_warn_count) { - write_eof_packet(thd); + write_eof_packet(thd, server_status, total_warn_count); thd->cur_data= 0; } @@ -1034,6 +1066,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ei->last_errno= sql_errno; strmake(ei->info, err, sizeof(ei->info)-1); strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno)); + ei->server_status= thd->server_status; thd->cur_data= 0; } diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index eb47a045669..a8542f6fca9 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -209,8 +209,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_RETURN(mysql); error: - DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno, - mysql->net.last_error)); + DBUG_PRINT("error",("message: %u (%s)", + mysql->net.client_last_errno, + mysql->net.client_last_error)); { /* Free alloced memory */ my_bool free_me=mysql->free_me; diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 78ff08e510a..2aa75c0b23c 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_ping mysql_query |