diff options
Diffstat (limited to 'sql')
162 files changed, 9775 insertions, 7629 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 2aef0e0dc25..85c2013d8e7 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -49,7 +49,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc item_create.cc item_func.cc item_geofunc.cc item_row.cc item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc key.cc log.cc lock.cc message.rc - log_event.cc rpl_record.cc + log_event.cc rpl_record.cc rpl_reporting.cc log_event_old.cc rpl_record_old.cc message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c mysqld.cc net_serv.cc diff --git a/sql/Makefile.am b/sql/Makefile.am index d280b22f493..a379a950c41 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -38,7 +38,8 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ @pstack_libs@ \ @mysql_plugin_libs@ \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \ - $(yassl_libs) $(openssl_libs) + $(yassl_libs) $(openssl_libs) \ + @MYSQLD_EXTRA_LIBS@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h \ @@ -52,6 +53,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \ ha_partition.h rpl_constants.h \ opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \ + rpl_reporting.h \ log.h sql_show.h rpl_rli.h rpl_mi.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ @@ -99,6 +101,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \ rpl_utility.cc rpl_injector.cc rpl_rli.cc rpl_mi.cc \ + rpl_reporting.cc \ sql_union.cc sql_derived.cc \ client.c sql_client.cc mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc \ diff --git a/sql/derror.cc b/sql/derror.cc index eca553d1bf8..3b67e0f5bf0 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -65,7 +65,7 @@ bool init_errmessage(void) /* Register messages for use with my_error(). */ if (my_error_register(errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST)) { - x_free((gptr) errmsgs); + x_free((uchar*) errmsgs); DBUG_RETURN(TRUE); } @@ -81,11 +81,13 @@ static bool read_texts(const char *file_name,const char ***point, uint error_messages) { register uint i; - uint count,funktpos,length,textcount; + uint count,funktpos,textcount; + size_t length; File file; char name[FN_REFLEN]; - const char *buff; + uchar *buff; uchar head[32],*pos; + const char *errmsg; DBUG_ENTER("read_texts"); LINT_INIT(buff); @@ -96,7 +98,7 @@ static bool read_texts(const char *file_name,const char ***point, goto err; /* purecov: inspected */ funktpos=1; - if (my_read(file,(byte*) head,32,MYF(MY_NABP))) goto err; + if (my_read(file,(uchar*) head,32,MYF(MY_NABP))) goto err; if (head[0] != (uchar) 254 || head[1] != (uchar) 254 || head[2] != 2 || head[3] != 1) goto err; /* purecov: inspected */ @@ -130,22 +132,24 @@ Check that the above file is the right version for this program!", DBUG_RETURN(1); } - x_free((gptr) *point); /* Free old language */ + x_free((uchar*) *point); /* Free old language */ if (!(*point= (const char**) - my_malloc((uint) (length+count*sizeof(char*)),MYF(0)))) + my_malloc((size_t) (length+count*sizeof(char*)),MYF(0)))) { funktpos=2; /* purecov: inspected */ goto err; /* purecov: inspected */ } - buff= (char*) (*point + count); + buff= (uchar*) (*point + count); - if (my_read(file,(byte*) buff,(uint) count*2,MYF(MY_NABP))) goto err; - for (i=0, pos= (uchar*) buff ; i< count ; i++) + if (my_read(file, buff, (size_t) count*2,MYF(MY_NABP))) + goto err; + for (i=0, pos= buff ; i< count ; i++) { - (*point)[i]=buff+uint2korr(pos); + (*point)[i]= (char*) buff+uint2korr(pos); pos+=2; } - if (my_read(file,(byte*) buff,(uint) length,MYF(MY_NABP))) goto err; + if (my_read(file, buff, length, MYF(MY_NABP))) + goto err; for (i=1 ; i < textcount ; i++) { @@ -157,16 +161,16 @@ Check that the above file is the right version for this program!", err: switch (funktpos) { case 2: - buff="Not enough memory for messagefile '%s'"; + errmsg= "Not enough memory for messagefile '%s'"; break; case 1: - buff="Can't read from messagefile '%s'"; + errmsg= "Can't read from messagefile '%s'"; break; default: - buff="Can't find messagefile '%s'"; + errmsg= "Can't find messagefile '%s'"; break; } - sql_print_error(buff,name); + sql_print_error(errmsg, name); err1: if (file != FERR) VOID(my_close(file,MYF(MY_WME))); diff --git a/sql/discover.cc b/sql/discover.cc index 395bfbfff45..a7af90c440f 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -39,14 +39,13 @@ frmdata and len are set to 0 on error */ -int readfrm(const char *name, - const void **frmdata, uint *len) +int readfrm(const char *name, uchar **frmdata, size_t *len) { int error; char index_file[FN_REFLEN]; File file; - ulong read_len; - char *read_data; + size_t read_len; + uchar *read_data; MY_STAT state; DBUG_ENTER("readfrm"); DBUG_PRINT("enter",("name: '%s'",name)); @@ -68,12 +67,12 @@ int readfrm(const char *name, // Read whole frm file error= 3; - read_data= 0; + read_data= 0; // Nothing to free if (read_string(file, &read_data, read_len)) goto err; // Setup return data - *frmdata= (void*) read_data; + *frmdata= (uchar*) read_data; *len= read_len; error= 0; @@ -102,21 +101,20 @@ int readfrm(const char *name, 2 Could not write file */ -int writefrm(const char *name, const void *frmdata, uint len) +int writefrm(const char *name, const uchar *frmdata, size_t len) { File file; char index_file[FN_REFLEN]; int error; DBUG_ENTER("writefrm"); - DBUG_PRINT("enter",("name: '%s' len: %d ",name,len)); - //DBUG_DUMP("frmdata", (char*)frmdata, len); + DBUG_PRINT("enter",("name: '%s' len: %lu ",name, (ulong) len)); error= 0; if ((file=my_create(fn_format(index_file,name,"",reg_ext, MY_UNPACK_FILENAME|MY_APPEND_EXT), CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { - if (my_write(file,(byte*)frmdata,len,MYF(MY_WME | MY_NABP))) + if (my_write(file, frmdata, len,MYF(MY_WME | MY_NABP))) error= 2; VOID(my_close(file,MYF(0))); } diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 9394bdcdae5..77dc33e6265 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -42,7 +42,7 @@ Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n) return TRUE; if (!(name.str= my_strndup(n.str, name.length= n.length, MYF(MY_WME)))) { - my_free((gptr) dbname.str, MYF(0)); + my_free((uchar*) dbname.str, MYF(0)); return TRUE; } return FALSE; @@ -58,8 +58,8 @@ Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n) Event_queue_element_for_exec::~Event_queue_element_for_exec() { - my_free((gptr) dbname.str, MYF(0)); - my_free((gptr) name.str, MYF(0)); + my_free((uchar*) dbname.str, MYF(0)); + my_free((uchar*) name.str, MYF(0)); } @@ -94,17 +94,18 @@ Event_parse_data::Event_parse_data() :on_completion(Event_basic::ON_COMPLETION_DROP), status(Event_basic::ENABLED), do_not_create(FALSE), - item_starts(NULL), item_ends(NULL), item_execute_at(NULL), - starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE), - item_expression(NULL), expression(0) + body_changed(FALSE), + item_starts(NULL), item_ends(NULL), item_execute_at(NULL), + starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE), + item_expression(NULL), expression(0) { DBUG_ENTER("Event_parse_data::Event_parse_data"); /* Actually in the parser STARTS is always set */ starts= ends= execute_at= 0; - body.str= comment.str= NULL; - body.length= comment.length= 0; + comment.str= NULL; + comment.length= 0; DBUG_VOID_RETURN; } @@ -138,86 +139,6 @@ Event_parse_data::init_name(THD *thd, sp_name *spn) /* - Set body of the event - what should be executed. - - SYNOPSIS - Event_parse_data::init_body() - thd THD - - NOTE - The body is extracted by copying all data between the - start of the body set by another method and the current pointer in Lex. - - Some questionable removal of characters is done in here, and that part - should be refactored when the parser is smarter. -*/ - -void -Event_parse_data::init_body(THD *thd) -{ - DBUG_ENTER("Event_parse_data::init_body"); - - /* This method is called from within the parser, from sql_yacc.yy */ - DBUG_ASSERT(thd->m_lip != NULL); - - DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin, - (long) body_begin, (long) thd->m_lip->ptr)); - - body.length= thd->m_lip->ptr - body_begin; - const char *body_end= body_begin + body.length - 1; - - /* Trim nuls or close-comments ('*'+'/') or spaces at the end */ - while (body_begin < body_end) - { - - if ((*body_end == '\0') || - (my_isspace(thd->variables.character_set_client, *body_end))) - { /* consume NULs and meaningless whitespace */ - --body.length; - --body_end; - continue; - } - - /* - consume closing comments - - This is arguably wrong, but it's the best we have until the parser is - changed to be smarter. FIXME PARSER - - See also the sp_head code, where something like this is done also. - - One idea is to keep in the lexer structure the count of the number of - open-comments we've entered, and scan left-to-right looking for a - closing comment IFF the count is greater than zero. - - Another idea is to remove the closing comment-characters wholly in the - parser, since that's where it "removes" the opening characters. - */ - if ((*(body_end - 1) == '*') && (*body_end == '/')) - { - DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'", - body_begin)); - body.length-= 2; - body_end-= 2; - continue; - } - - break; /* none were found, so we have excised all we can. */ - } - - /* the first is always whitespace which I cannot skip in the parser */ - while (my_isspace(thd->variables.character_set_client, *body_begin)) - { - ++body_begin; - --body.length; - } - body.str= thd->strmake(body_begin, body.length); - - DBUG_VOID_RETURN; -} - - -/* This function is called on CREATE EVENT or ALTER EVENT. When either ENDS or AT is in the past, we are trying to create an event that will never be executed. If it has ON COMPLETION NOT PRESERVE @@ -413,7 +334,8 @@ Event_parse_data::init_interval(THD *thd) default: ;/* these are the microsec stuff */ } - if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE) + if (interval_tmp.neg || expression == 0 || + expression > EVEX_MAX_INTERVAL_VALUE) { my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0)); DBUG_RETURN(EVEX_BAD_PARAMS); @@ -619,7 +541,7 @@ Event_parse_data::init_definer(THD *thd) /* + 1 for @ */ DBUG_PRINT("info",("init definer as whole")); definer.length= definer_user_len + definer_host_len + 1; - definer.str= thd->alloc(definer.length + 1); + definer.str= (char*) thd->alloc(definer.length + 1); DBUG_PRINT("info",("copy the user")); memcpy(definer.str, definer_user, definer_user_len); @@ -837,36 +759,32 @@ Event_timed::init() } -/* - Loads an event's body from a row from mysql.event - - SYNOPSIS - Event_job_data::load_from_row(THD *thd, TABLE *table) - - RETURN VALUE - 0 OK - EVEX_GET_FIELD_FAILED Error - - NOTES - This method is silent on errors and should behave like that. Callers - should handle throwing of error messages. The reason is that the class - should not know about how to deal with communication. +/** + Load an event's body from a row from mysql.event. + @details This method is silent on errors and should behave like that. + Callers should handle throwing of error messages. The reason is that the + class should not know about how to deal with communication. + + @return Operation status + @retval FALSE OK + @retval TRUE Error */ -int +bool Event_job_data::load_from_row(THD *thd, TABLE *table) { char *ptr; uint len; + LEX_STRING tz_name; + DBUG_ENTER("Event_job_data::load_from_row"); if (!table) - goto error; + DBUG_RETURN(TRUE); if (table->s->fields < ET_FIELD_COUNT) - goto error; + DBUG_RETURN(TRUE); - LEX_STRING tz_name; if (load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name, @@ -874,10 +792,10 @@ Event_job_data::load_from_row(THD *thd, TABLE *table) ET_FIELD_DEFINER, &definer, ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT)) - goto error; + DBUG_RETURN(TRUE); if (load_time_zone(thd, tz_name)) - goto error; + DBUG_RETURN(TRUE); ptr= strchr(definer.str, '@'); @@ -894,29 +812,23 @@ Event_job_data::load_from_row(THD *thd, TABLE *table) sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int(); - DBUG_RETURN(0); -error: - DBUG_RETURN(EVEX_GET_FIELD_FAILED); + DBUG_RETURN(FALSE); } -/* - Loads an event from a row from mysql.event +/** + Load an event's body from a row from mysql.event. - SYNOPSIS - Event_queue_element::load_from_row(THD *thd, TABLE *table) + @details This method is silent on errors and should behave like that. + Callers should handle throwing of error messages. The reason is that the + class should not know about how to deal with communication. - RETURN VALUE - 0 OK - EVEX_GET_FIELD_FAILED Error - - NOTES - This method is silent on errors and should behave like that. Callers - should handle throwing of error messages. The reason is that the class - should not know about how to deal with communication. + @return Operation status + @retval FALSE OK + @retval TRUE Error */ -int +bool Event_queue_element::load_from_row(THD *thd, TABLE *table) { char *ptr; @@ -926,10 +838,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) DBUG_ENTER("Event_queue_element::load_from_row"); if (!table) - goto error; + DBUG_RETURN(TRUE); if (table->s->fields < ET_FIELD_COUNT) - goto error; + DBUG_RETURN(TRUE); if (load_string_fields(table->field, ET_FIELD_DB, &dbname, @@ -937,10 +849,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) ET_FIELD_DEFINER, &definer, ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT)) - goto error; + DBUG_RETURN(TRUE); if (load_time_zone(thd, tz_name)) - goto error; + DBUG_RETURN(TRUE); starts_null= table->field[ET_FIELD_STARTS]->is_null(); if (!starts_null) @@ -970,7 +882,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) { if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, TIME_NO_ZERO_DATE)) - goto error; + DBUG_RETURN(TRUE); execute_at= sec_since_epoch_TIME(&time); } @@ -989,13 +901,13 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str); if (!(tmp.length= str.length())) - goto error; + DBUG_RETURN(TRUE); tmp.str= str.c_ptr_safe(); i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info); if (i < 0) - goto error; + DBUG_RETURN(TRUE); interval= (interval_type) i; } @@ -1008,7 +920,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) last_executed_changed= FALSE; if ((ptr= get_field(&mem_root, table->field[ET_FIELD_STATUS])) == NullS) - goto error; + DBUG_RETURN(TRUE); DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr)); @@ -1027,40 +939,34 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) break; } if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS) - goto error; + DBUG_RETURN(TRUE); originator = table->field[ET_FIELD_ORIGINATOR]->val_int(); /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */ if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ON_COMPLETION])) == NullS) - goto error; + DBUG_RETURN(TRUE); on_completion= (ptr[0]=='D'? Event_queue_element::ON_COMPLETION_DROP: Event_queue_element::ON_COMPLETION_PRESERVE); - DBUG_RETURN(0); -error: - DBUG_RETURN(EVEX_GET_FIELD_FAILED); + DBUG_RETURN(FALSE); } -/* - Loads an event from a row from mysql.event - - SYNOPSIS - Event_timed::load_from_row(THD *thd, TABLE *table) +/** + Load an event's body from a row from mysql.event. - RETURN VALUE - 0 OK - EVEX_GET_FIELD_FAILED Error + @details This method is silent on errors and should behave like that. + Callers should handle throwing of error messages. The reason is that the + class should not know about how to deal with communication. - NOTES - This method is silent on errors and should behave like that. Callers - should handle throwing of error messages. The reason is that the class - should not know about how to deal with communication. + @return Operation status + @retval FALSE OK + @retval TRUE Error */ -int +bool Event_timed::load_from_row(THD *thd, TABLE *table) { char *ptr; @@ -1069,12 +975,12 @@ Event_timed::load_from_row(THD *thd, TABLE *table) DBUG_ENTER("Event_timed::load_from_row"); if (Event_queue_element::load_from_row(thd, table)) - goto error; + DBUG_RETURN(TRUE); if (load_string_fields(table->field, ET_FIELD_BODY, &body, ET_FIELD_COUNT)) - goto error; + DBUG_RETURN(TRUE); ptr= strchr(definer.str, '@'); @@ -1101,9 +1007,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table) sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int(); - DBUG_RETURN(0); -error: - DBUG_RETURN(EVEX_GET_FIELD_FAILED); + DBUG_RETURN(FALSE); } @@ -1635,7 +1539,7 @@ Event_queue_element::update_timing_fields(THD *thd) DBUG_ENTER("Event_queue_element::update_timing_fields"); - DBUG_PRINT("enter", ("name: %*s", name.length, name.str)); + DBUG_PRINT("enter", ("name: %*s", (int) name.length, name.str)); /* No need to update if nothing has changed */ if (!(status_changed || last_executed_changed)) @@ -1695,7 +1599,8 @@ Event_timed::get_create_event(THD *thd, String *buf) expr_buf.length(0); DBUG_ENTER("get_create_event"); - DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str)); + DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", + (int) body.length, body.str)); if (expression && Events::reconstruct_interval_expression(&expr_buf, interval, expression)) @@ -1923,11 +1828,9 @@ Event_job_data::execute(THD *thd, bool drop) { Lex_input_stream lip(thd, thd->query, thd->query_length); - thd->m_lip= &lip; lex_start(thd); - int err= MYSQLparse(thd); - if (err || thd->is_fatal_error) + if (parse_sql(thd, &lip)) { sql_print_error("Event Scheduler: " "%serror during compilation of %s.%s", @@ -1997,6 +1900,9 @@ end: thd->lex->unit.cleanup(); thd->end_statement(); thd->cleanup_after_query(); + /* Avoid races with SHOW PROCESSLIST */ + thd->query_length= 0; + thd->query= NULL; DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret)); diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index 8e03ab19602..d79732780ff 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -77,7 +77,7 @@ public: Event_basic(); virtual ~Event_basic(); - virtual int + virtual bool load_from_row(THD *thd, TABLE *table) = 0; protected: @@ -119,7 +119,7 @@ public: Event_queue_element(); virtual ~Event_queue_element(); - virtual int + virtual bool load_from_row(THD *thd, TABLE *table); bool @@ -157,7 +157,7 @@ public: void init(); - virtual int + virtual bool load_from_row(THD *thd, TABLE *table); int @@ -176,7 +176,7 @@ public: Event_job_data(); - virtual int + virtual bool load_from_row(THD *thd, TABLE *table); bool @@ -205,12 +205,11 @@ public: */ bool do_not_create; - const char *body_begin; + bool body_changed; LEX_STRING dbname; LEX_STRING name; LEX_STRING definer;// combination of user and host - LEX_STRING body; LEX_STRING comment; Item* item_starts; @@ -235,9 +234,6 @@ public: bool check_parse_data(THD *thd); - void - init_body(THD *thd); - private: void diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index e49fd6791a0..703c4160216 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -15,6 +15,7 @@ #include "mysql_priv.h" #include "event_db_repository.h" +#include "sp_head.h" #include "event_data_objects.h" #include "events.h" #include "sql_show.h" @@ -141,7 +142,10 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = */ static bool -mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, +mysql_event_fill_row(THD *thd, + TABLE *table, + Event_parse_data *et, + sp_head *sp, my_bool is_update) { CHARSET_INFO *scs= system_charset_info; @@ -152,7 +156,6 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str)); DBUG_PRINT("info", ("name =[%s]", et->name.str)); - DBUG_PRINT("info", ("body =[%s]", et->body.str)); if (table->s->fields < ET_FIELD_COUNT) { @@ -187,11 +190,18 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, Change the SQL_MODE only if body was present in an ALTER EVENT and of course always during CREATE EVENT. */ - if (et->body.str) + if (et->body_changed) { + DBUG_ASSERT(sp->m_body.str); + fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE); - if (fields[f_num= ET_FIELD_BODY]->store(et->body.str, et->body.length, scs)) + + if (fields[f_num= ET_FIELD_BODY]->store(sp->m_body.str, + sp->m_body.length, + scs)) + { goto err_truncate; + } } if (et->expression) @@ -303,7 +313,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, CHARSET_INFO *scs= system_charset_info; KEY *key_info; uint key_len; - byte *key_buf= NULL; + uchar *key_buf= NULL; LINT_INIT(key_buf); DBUG_ENTER("Event_db_repository::index_read_for_db_for_i_s"); @@ -324,7 +334,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, event_table->field[ET_FIELD_DB]->store(db, strlen(db), scs); key_len= key_info->key_part[0].store_length; - if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len))) + if (!(key_buf= (uchar *)alloc_root(thd->mem_root, key_len))) { /* Don't send error, it would be done by sql_alloc_error_handler() */ ret= 1; @@ -513,15 +523,17 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, { int ret= 1; TABLE *table= NULL; + sp_head *sp= thd->lex->sphead; DBUG_ENTER("Event_db_repository::create_event"); DBUG_PRINT("info", ("open mysql.event for update")); + DBUG_ASSERT(sp); if (open_event_table(thd, TL_WRITE, &table)) goto end; - DBUG_PRINT("info", ("name: %.*s", parse_data->name.length, + DBUG_PRINT("info", ("name: %.*s", (int) parse_data->name.length, parse_data->name.str)); DBUG_PRINT("info", ("check existance of an event with the same name")); @@ -561,7 +573,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, goto end; } - if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length) + if (sp->m_body.length > table->field[ET_FIELD_BODY]->field_length) { my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str); goto end; @@ -573,7 +585,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, mysql_event_fill_row() calls my_error() in case of error so no need to handle it here */ - if (mysql_event_fill_row(thd, table, parse_data, FALSE)) + if (mysql_event_fill_row(thd, table, parse_data, sp, FALSE)) goto end; table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE); @@ -617,7 +629,9 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, { CHARSET_INFO *scs= system_charset_info; TABLE *table= NULL; + sp_head *sp= thd->lex->sphead; int ret= 1; + DBUG_ENTER("Event_db_repository::update_event"); /* None or both must be set */ @@ -661,7 +675,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, mysql_event_fill_row() calls my_error() in case of error so no need to handle it here */ - if (mysql_event_fill_row(thd, table, parse_data, TRUE)) + if (mysql_event_fill_row(thd, table, parse_data, sp, TRUE)) goto end; if (new_dbname) @@ -757,9 +771,9 @@ bool Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name, TABLE *table) { - byte key[MAX_KEY_LENGTH]; + uchar key[MAX_KEY_LENGTH]; DBUG_ENTER("Event_db_repository::find_named_event"); - DBUG_PRINT("enter", ("name: %.*s", name.length, name.str)); + DBUG_PRINT("enter", ("name: %.*s", (int) name.length, name.str)); /* Create key to find row. We have to use field->store() to be able to @@ -879,7 +893,8 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, bool ret; DBUG_ENTER("Event_db_repository::load_named_event"); - DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, name.length, name.str)); + DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, + (int) name.length, name.str)); if (!(ret= open_event_table(thd, TL_READ, &table))) { diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 5593e80b41b..634cc764d74 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -53,7 +53,7 @@ */ static int -event_queue_element_compare_q(void *vptr, byte* a, byte *b) +event_queue_element_compare_q(void *vptr, uchar* a, uchar *b) { my_time_t lhs = ((Event_queue_element *)a)->execute_at; my_time_t rhs = ((Event_queue_element *)b)->execute_at; @@ -70,15 +70,17 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b) */ Event_queue::Event_queue() - :mutex_last_locked_at_line(0), mutex_last_unlocked_at_line(0), + :next_activation_at(0), + mutex_last_locked_at_line(0), + mutex_last_unlocked_at_line(0), mutex_last_attempted_lock_at_line(0), + mutex_last_locked_in_func("n/a"), + mutex_last_unlocked_in_func("n/a"), + mutex_last_attempted_lock_in_func("n/a"), mutex_queue_data_locked(FALSE), - next_activation_at(0), - mutex_queue_data_attempting_lock(FALSE) + mutex_queue_data_attempting_lock(FALSE), + waiting_on_cond(FALSE) { - mutex_last_unlocked_in_func= mutex_last_locked_in_func= - mutex_last_attempted_lock_in_func= ""; - pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_queue_state, NULL); } @@ -193,7 +195,7 @@ Event_queue::create_event(THD *thd, Event_queue_element *new_element, DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); LOCK_QUEUE_DATA(); - *created= (queue_insert_safe(&queue, (byte *) new_element) == FALSE); + *created= (queue_insert_safe(&queue, (uchar *) new_element) == FALSE); dbug_dump_queue(thd->query_start()); pthread_cond_broadcast(&COND_queue_state); UNLOCK_QUEUE_DATA(); @@ -242,7 +244,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, if (new_element) { DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); - queue_insert_safe(&queue, (byte *) new_element); + queue_insert_safe(&queue, (uchar *) new_element); pthread_cond_broadcast(&COND_queue_state); } @@ -739,8 +741,11 @@ Event_queue::dump_internal_status() MYSQL_TIME time; my_tz_UTC->gmt_sec_to_TIME(&time, next_activation_at); - printf("Next activation : %04d-%02d-%02d %02d:%02d:%02d\n", - time.year, time.month, time.day, time.hour, time.minute, time.second); + if (time.year != 1970) + printf("Next activation : %04d-%02d-%02d %02d:%02d:%02d\n", + time.year, time.month, time.day, time.hour, time.minute, time.second); + else + printf("Next activation : never"); DBUG_VOID_RETURN; } diff --git a/sql/event_queue.h b/sql/event_queue.h index 04bb8b93b06..ac4a4f2bfd7 100644 --- a/sql/event_queue.h +++ b/sql/event_queue.h @@ -104,7 +104,6 @@ private: bool mutex_queue_data_locked; bool mutex_queue_data_attempting_lock; bool waiting_on_cond; - }; #endif /* _EVENT_QUEUE_H_ */ diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 5844fecc227..c552b22e942 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -42,7 +42,6 @@ Event_db_repository *Event_worker_thread::db_repository; static const LEX_STRING scheduler_states_names[] = { - { C_STRING_WITH_LEN("UNINITIALIZED") }, { C_STRING_WITH_LEN("INITIALIZED") }, { C_STRING_WITH_LEN("RUNNING") }, { C_STRING_WITH_LEN("STOPPING") } @@ -327,13 +326,21 @@ end: delete event; deinit_event_thread(thd); + + DBUG_VOID_RETURN; } Event_scheduler::Event_scheduler(Event_queue *queue_arg) - :state(UNINITIALIZED), + :state(INITIALIZED), scheduler_thd(NULL), queue(queue_arg), + mutex_last_locked_at_line(0), + mutex_last_unlocked_at_line(0), + mutex_last_locked_in_func("n/a"), + mutex_last_unlocked_in_func("n/a"), + mutex_scheduler_data_locked(FALSE), + waiting_on_cond(FALSE), started_events(0) { pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST); diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index 70635196745..eba66c68d42 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -111,8 +111,7 @@ private: enum enum_state { - UNINITIALIZED = 0, - INITIALIZED, + INITIALIZED = 0, RUNNING, STOPPING }; diff --git a/sql/field.cc b/sql/field.cc index fa25871fe61..55a93ed46d6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -38,8 +38,8 @@ *****************************************************************************/ #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION -template class List<create_field>; -template class List_iterator<create_field>; +template class List<Create_field>; +template class List_iterator<Create_field>; #endif uchar Field_null::null[1]={1}; @@ -1051,7 +1051,7 @@ bool Field::type_can_have_key_part(enum enum_field_types type) /* Numeric fields base class constructor */ -Field_num::Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, +Field_num::Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg) @@ -1071,9 +1071,10 @@ void Field_num::prepend_zeros(String *value) int diff; if ((diff= (int) (field_length - value->length())) > 0) { - bmove_upp((char*) value->ptr()+field_length,value->ptr()+value->length(), + bmove_upp((uchar*) value->ptr()+field_length, + (uchar*) value->ptr()+value->length(), value->length()); - bfill((char*) value->ptr(),diff,'0'); + bfill((uchar*) value->ptr(),diff,'0'); value->length(field_length); (void) value->c_ptr_quick(); // Avoid warnings in purify } @@ -1155,7 +1156,8 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len, char *end; int error; - *rnd= (longlong) cs->cset->strntoull10rnd(cs, from, len, unsigned_flag, &end, + *rnd= (longlong) cs->cset->strntoull10rnd(cs, from, len, + unsigned_flag, &end, &error); if (unsigned_flag) { @@ -1179,7 +1181,8 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len, goto out_of_range; } } - if (table->in_use->count_cuted_fields && check_int(cs, from, len, end, error)) + if (table->in_use->count_cuted_fields && + check_int(cs, from, len, end, error)) return 1; return 0; @@ -1296,7 +1299,7 @@ String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val) } -Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, +Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg) :ptr(ptr_arg), null_ptr(null_ptr_arg), @@ -1323,18 +1326,17 @@ void Field::hash(ulong *nr, ulong *nr2) { uint len= pack_length(); CHARSET_INFO *cs= charset(); - cs->coll->hash_sort(cs, (uchar*) ptr, len, nr, nr2); + cs->coll->hash_sort(cs, ptr, len, nr, nr2); } } -my_size_t +size_t Field::do_last_null_byte() const { - DBUG_ASSERT(null_ptr == NULL || (byte*) null_ptr >= table->record[0]); + DBUG_ASSERT(null_ptr == NULL || null_ptr >= table->record[0]); if (null_ptr) - return (byte*) null_ptr - table->record[0] + 1; - else - return LAST_NULL_BYTE_UNDEF; + return (size_t) (null_ptr - table->record[0]) + 1; + return LAST_NULL_BYTE_UNDEF; } @@ -1488,7 +1490,7 @@ my_decimal* Field_num::val_decimal(my_decimal *decimal_value) } -Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, +Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *charset_arg) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, @@ -1639,7 +1641,7 @@ Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table, Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit) { Field *tmp; @@ -1693,7 +1695,7 @@ Field_decimal::reset(void) void Field_decimal::overflow(bool negative) { uint len=field_length; - char *to=ptr, filler= '9'; + uchar *to=ptr, filler= '9'; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); if (negative) @@ -1729,36 +1731,37 @@ void Field_decimal::overflow(bool negative) } -int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) +int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) { ASSERT_COLUMN_MARKED_FOR_WRITE; char buff[STRING_BUFFER_USUAL_SIZE]; String tmp(buff,sizeof(buff), &my_charset_bin); + const uchar *from= (uchar*) from_arg; - /* Convert character set if the old one is multi byte */ + /* Convert character set if the old one is multi uchar */ if (cs->mbmaxlen > 1) { uint dummy_errors; - tmp.copy(from, len, cs, &my_charset_bin, &dummy_errors); - from= tmp.ptr(); + tmp.copy((char*) from, len, cs, &my_charset_bin, &dummy_errors); + from= (uchar*) tmp.ptr(); len= tmp.length(); } - const char *end= from+len; + const uchar *end= from+len; /* The pointer where the field value starts (i.e., "where to write") */ - char *to=ptr; + uchar *to= ptr; uint tmp_dec, tmp_uint; /* The sign of the number : will be 0 (means positive but sign not specified), '+' or '-' */ - char sign_char=0; + uchar sign_char=0; /* The pointers where prezeros start and stop */ - const char *pre_zeros_from, *pre_zeros_end; + const uchar *pre_zeros_from, *pre_zeros_end; /* The pointers where digits at the left of '.' start and stop */ - const char *int_digits_from, *int_digits_end; + const uchar *int_digits_from, *int_digits_end; /* The pointers where digits at the right of '.' start and stop */ - const char *frac_digits_from, *frac_digits_end; + const uchar *frac_digits_from, *frac_digits_end; /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */ char expo_sign_char=0; uint exponent=0; // value of the exponent @@ -1766,20 +1769,20 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) Pointers used when digits move from the left of the '.' to the right of the '.' (explained below) */ - const char *int_digits_tail_from; + const uchar *int_digits_tail_from; /* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */ uint int_digits_added_zeros; /* Pointer used when digits move from the right of the '.' to the left of the '.' */ - const char *frac_digits_head_end; + const uchar *frac_digits_head_end; /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */ uint frac_digits_added_zeros; - char *pos,*tmp_left_pos,*tmp_right_pos; + uchar *pos,*tmp_left_pos,*tmp_right_pos; /* Pointers that are used as limits (begin and end of the field buffer) */ - char *left_wall,*right_wall; - char tmp_char; + uchar *left_wall,*right_wall; + uchar tmp_char; /* To remember if table->in_use->cuted_fields has already been incremented, to do that only once @@ -2116,17 +2119,18 @@ int Field_decimal::store(double nr) } #endif - reg4 uint i,length; - char fyllchar,*to; + reg4 uint i; + size_t length; + uchar fyllchar,*to; char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; fyllchar = zerofill ? (char) '0' : (char) ' '; #ifdef HAVE_SNPRINTF buff[sizeof(buff)-1]=0; // Safety snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr); - length=(uint) strlen(buff); + length= strlen(buff); #else - length=(uint) my_sprintf(buff,(buff,"%.*f",dec,nr)); + length= my_sprintf(buff,(buff,"%.*f",dec,nr)); #endif if (length > field_length) @@ -2150,7 +2154,8 @@ int Field_decimal::store(longlong nr, bool unsigned_val) ASSERT_COLUMN_MARKED_FOR_WRITE; char buff[22]; uint length, int_part; - char fyllchar, *to; + char fyllchar; + uchar *to; if (nr < 0 && unsigned_flag && !unsigned_val) { @@ -2185,7 +2190,7 @@ double Field_decimal::val_real(void) ASSERT_COLUMN_MARKED_FOR_READ; int not_used; char *end_not_used; - return my_strntod(&my_charset_bin, ptr, field_length, &end_not_used, + return my_strntod(&my_charset_bin, (char*) ptr, field_length, &end_not_used, ¬_used); } @@ -2194,11 +2199,10 @@ longlong Field_decimal::val_int(void) ASSERT_COLUMN_MARKED_FOR_READ; int not_used; if (unsigned_flag) - return my_strntoull(&my_charset_bin, ptr, field_length, 10, NULL, - ¬_used); - else - return my_strntoll(&my_charset_bin, ptr, field_length, 10, NULL, + return my_strntoull(&my_charset_bin, (char*) ptr, field_length, 10, NULL, ¬_used); + return my_strntoll(&my_charset_bin, (char*) ptr, field_length, 10, NULL, + ¬_used); } @@ -2206,10 +2210,12 @@ String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { ASSERT_COLUMN_MARKED_FOR_READ; - char *str; + uchar *str; + size_t tmp_length; + for (str=ptr ; *str == ' ' ; str++) ; - uint tmp_length=(uint) (str-ptr); val_ptr->set_charset(&my_charset_bin); + tmp_length= (size_t) (str-ptr); if (field_length < tmp_length) // Error in data val_ptr->length(0); else @@ -2222,9 +2228,9 @@ String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), ** 5.00 , -1.0, 05, -05, +5 with optional pre/end space */ -int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) +int Field_decimal::cmp(const uchar *a_ptr,const uchar *b_ptr) { - const char *end; + const uchar *end; int swap=0; /* First remove prefixes '0', ' ', and '-' */ for (end=a_ptr+field_length; @@ -2255,9 +2261,9 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) } -void Field_decimal::sort_string(char *to,uint length) +void Field_decimal::sort_string(uchar *to,uint length) { - char *str,*end; + uchar *str,*end; for (str=ptr,end=ptr+length; str != end && ((my_isspace(&my_charset_bin,*str) || *str == '+' || @@ -2299,7 +2305,7 @@ void Field_decimal::sql_type(String &res) const ** Field_new_decimal ****************************************************************************/ -Field_new_decimal::Field_new_decimal(char *ptr_arg, +Field_new_decimal::Field_new_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, @@ -2321,7 +2327,7 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, const char *name, uint8 dec_arg, bool unsigned_arg) - :Field_num((char*) 0, len_arg, + :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, name, dec_arg, 0, unsigned_arg) { @@ -2419,7 +2425,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec); error= 1; } - DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, + DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (uchar *) ptr, bin_size);); DBUG_RETURN(error); } @@ -2434,8 +2440,9 @@ int Field_new_decimal::store(const char *from, uint length, DBUG_ENTER("Field_new_decimal::store(char*)"); if ((err= str2my_decimal(E_DEC_FATAL_ERROR & - ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM), - from, length, charset_arg, &decimal_value)) && + ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM), + from, length, charset_arg, + &decimal_value)) && table->in_use->abort_on_warning) { /* Because "from" is not NUL-terminated and we use %s in the ER() */ @@ -2584,7 +2591,7 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value) DBUG_ENTER("Field_new_decimal::val_decimal"); binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value, precision, dec); - DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, + DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (uchar *) ptr, bin_size);); DBUG_RETURN(decimal_value); } @@ -2602,13 +2609,13 @@ String *Field_new_decimal::val_str(String *val_buffer, } -int Field_new_decimal::cmp(const char *a,const char*b) +int Field_new_decimal::cmp(const uchar *a,const uchar*b) { return memcmp(a, b, bin_size); } -void Field_new_decimal::sort_string(char *buff, +void Field_new_decimal::sort_string(uchar *buff, uint length __attribute__((unused))) { memcpy(buff, ptr, bin_size); @@ -2624,7 +2631,7 @@ void Field_new_decimal::sql_type(String &str) const } -uint Field_new_decimal::is_equal(create_field *new_field) +uint Field_new_decimal::is_equal(Create_field *new_field) { return ((new_field->sql_type == real_type()) && ((new_field->flags & UNSIGNED_FLAG) == @@ -2743,7 +2750,7 @@ int Field_tiny::store(longlong nr, bool unsigned_val) double Field_tiny::val_real(void) { ASSERT_COLUMN_MARKED_FOR_READ; - int tmp= unsigned_flag ? (int) ((uchar*) ptr)[0] : + int tmp= unsigned_flag ? (int) ptr[0] : (int) ((signed char*) ptr)[0]; return (double) tmp; } @@ -2752,7 +2759,7 @@ double Field_tiny::val_real(void) longlong Field_tiny::val_int(void) { ASSERT_COLUMN_MARKED_FOR_READ; - int tmp= unsigned_flag ? (int) ((uchar*) ptr)[0] : + int tmp= unsigned_flag ? (int) ptr[0] : (int) ((signed char*) ptr)[0]; return (longlong) tmp; } @@ -2770,7 +2777,7 @@ String *Field_tiny::val_str(String *val_buffer, if (unsigned_flag) length= (uint) cs->cset->long10_to_str(cs,to,mlength, 10, - (long) *((uchar*) ptr)); + (long) *ptr); else length= (uint) cs->cset->long10_to_str(cs,to,mlength,-10, (long) *((signed char*) ptr)); @@ -2786,7 +2793,7 @@ bool Field_tiny::send_binary(Protocol *protocol) return protocol->store_tiny((longlong) (int8) ptr[0]); } -int Field_tiny::cmp(const char *a_ptr, const char *b_ptr) +int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr) { signed char a,b; a=(signed char) a_ptr[0]; b= (signed char) b_ptr[0]; @@ -2795,12 +2802,12 @@ int Field_tiny::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_tiny::sort_string(char *to,uint length __attribute__((unused))) +void Field_tiny::sort_string(uchar *to,uint length __attribute__((unused))) { if (unsigned_flag) *to= *ptr; else - to[0] = (char) ((uchar) ptr[0] ^ (uchar) 128); /* Revers signbit */ + to[0] = (char) (ptr[0] ^ (uchar) 128); /* Revers signbit */ } void Field_tiny::sql_type(String &res) const @@ -3005,7 +3012,7 @@ bool Field_short::send_binary(Protocol *protocol) } -int Field_short::cmp(const char *a_ptr, const char *b_ptr) +int Field_short::cmp(const uchar *a_ptr, const uchar *b_ptr) { short a,b; #ifdef WORDS_BIGENDIAN @@ -3027,7 +3034,7 @@ int Field_short::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_short::sort_string(char *to,uint length __attribute__((unused))) +void Field_short::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table->s->db_low_byte_first) @@ -3213,7 +3220,7 @@ bool Field_medium::send_binary(Protocol *protocol) } -int Field_medium::cmp(const char *a_ptr, const char *b_ptr) +int Field_medium::cmp(const uchar *a_ptr, const uchar *b_ptr) { long a,b; if (unsigned_flag) @@ -3229,7 +3236,7 @@ int Field_medium::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_medium::sort_string(char *to,uint length __attribute__((unused))) +void Field_medium::sort_string(uchar *to,uint length __attribute__((unused))) { if (unsigned_flag) to[0] = ptr[2]; @@ -3440,7 +3447,7 @@ bool Field_long::send_binary(Protocol *protocol) return protocol->store_long(Field_long::val_int()); } -int Field_long::cmp(const char *a_ptr, const char *b_ptr) +int Field_long::cmp(const uchar *a_ptr, const uchar *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN @@ -3460,7 +3467,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_long::sort_string(char *to,uint length __attribute__((unused))) +void Field_long::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table->s->db_low_byte_first) @@ -3680,7 +3687,7 @@ bool Field_longlong::send_binary(Protocol *protocol) } -int Field_longlong::cmp(const char *a_ptr, const char *b_ptr) +int Field_longlong::cmp(const uchar *a_ptr, const uchar *b_ptr) { longlong a,b; #ifdef WORDS_BIGENDIAN @@ -3701,7 +3708,7 @@ int Field_longlong::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_longlong::sort_string(char *to,uint length __attribute__((unused))) +void Field_longlong::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table->s->db_low_byte_first) @@ -3769,56 +3776,9 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) int Field_float::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; - float j; - int error= 0; + int error= truncate(&nr, FLT_MAX); + float j= (float)nr; - if (isnan(nr)) - { - j= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - j= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (dec >= NOT_FIXED_DEC) - { - max_value= FLT_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - /* - The following comparison is needed to not get an overflow if nr - is close to FLT_MAX - */ - if (fabs(nr) < FLT_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - j= (float)-max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - j= (float)max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - j= (float) nr; - } - #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -3826,7 +3786,7 @@ int Field_float::store(double nr) } else #endif - memcpy_fixed(ptr,(byte*) &j,sizeof(j)); + memcpy_fixed(ptr,(uchar*) &j,sizeof(j)); return error; } @@ -3849,7 +3809,7 @@ double Field_float::val_real(void) } else #endif - memcpy_fixed((byte*) &j,ptr,sizeof(j)); + memcpy_fixed((uchar*) &j,ptr,sizeof(j)); return ((double) j); } @@ -3863,7 +3823,7 @@ longlong Field_float::val_int(void) } else #endif - memcpy_fixed((byte*) &j,ptr,sizeof(j)); + memcpy_fixed((uchar*) &j,ptr,sizeof(j)); return (longlong) rint(j); } @@ -3880,7 +3840,7 @@ String *Field_float::val_str(String *val_buffer, } else #endif - memcpy_fixed((byte*) &nr,ptr,sizeof(nr)); + memcpy_fixed((uchar*) &nr,ptr,sizeof(nr)); uint to_length=max(field_length,70); val_buffer->alloc(to_length); @@ -3952,7 +3912,7 @@ String *Field_float::val_str(String *val_buffer, } -int Field_float::cmp(const char *a_ptr, const char *b_ptr) +int Field_float::cmp(const uchar *a_ptr, const uchar *b_ptr) { float a,b; #ifdef WORDS_BIGENDIAN @@ -3972,7 +3932,7 @@ int Field_float::cmp(const char *a_ptr, const char *b_ptr) #define FLT_EXP_DIG (sizeof(float)*8-FLT_MANT_DIG) -void Field_float::sort_string(char *to,uint length __attribute__((unused))) +void Field_float::sort_string(uchar *to,uint length __attribute__((unused))) { float nr; #ifdef WORDS_BIGENDIAN @@ -3984,7 +3944,7 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused))) #endif memcpy_fixed(&nr,ptr,sizeof(float)); - uchar *tmp= (uchar*) to; + uchar *tmp= to; if (nr == (float) 0.0) { /* Change to zero string */ tmp[0]=(uchar) 128; @@ -4062,48 +4022,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) int Field_double::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; - int error= 0; - - if (isnan(nr)) - { - nr= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - nr= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (not_fixed) - { - max_value= DBL_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - if (fabs(nr) < DBL_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - nr= -max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - nr= max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - } + int error= truncate(&nr, DBL_MAX); #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) @@ -4123,6 +4042,63 @@ int Field_double::store(longlong nr, bool unsigned_val) (double) nr); } +/* + If a field has fixed length, truncate the double argument pointed to by 'nr' + appropriately. + Also ensure that the argument is within [-max_value; max_value] range. +*/ + +int Field_real::truncate(double *nr, double max_value) +{ + int error= 1; + double res= *nr; + + if (isnan(res)) + { + res= 0; + set_null(); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + else if (unsigned_flag && res < 0) + { + res= 0; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + + if (!not_fixed) + { + uint order= field_length - dec; + uint step= array_elements(log_10) - 1; + max_value= 1.0; + for (; order > step; order-= step) + max_value*= log_10[step]; + max_value*= log_10[order]; + max_value-= 1.0 / log_10[dec]; + + double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec]; + res= floor(res) + tmp; + } + + if (res < -max_value) + { + res= -max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else if (res > max_value) + { + res= max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else + error= 0; + +end: + *nr= res; + return error; +} + int Field_real::store_decimal(const my_decimal *dm) { @@ -4284,7 +4260,7 @@ bool Field_double::send_binary(Protocol *protocol) } -int Field_double::cmp(const char *a_ptr, const char *b_ptr) +int Field_double::cmp(const uchar *a_ptr, const uchar *b_ptr) { ASSERT_COLUMN_MARKED_FOR_READ; double a,b; @@ -4308,7 +4284,7 @@ int Field_double::cmp(const char *a_ptr, const char *b_ptr) /* The following should work for IEEE */ -void Field_double::sort_string(char *to,uint length __attribute__((unused))) +void Field_double::sort_string(uchar *to,uint length __attribute__((unused))) { double nr; #ifdef WORDS_BIGENDIAN @@ -4319,7 +4295,7 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused))) else #endif doubleget(nr,ptr); - change_double_for_sort(nr, (byte*) to); + change_double_for_sort(nr, to); } @@ -4384,13 +4360,13 @@ void Field_double::sql_type(String &res) const exception is different behavior of old/new timestamps during ALTER TABLE. */ -Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, +Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, TABLE_SHARE *share, CHARSET_INFO *cs) - :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, + :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ @@ -4407,7 +4383,8 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp::Field_timestamp(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((char*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0, + :Field_str((uchar*) 0, MAX_DATETIME_WIDTH, + maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ @@ -4720,7 +4697,7 @@ bool Field_timestamp::send_binary(Protocol *protocol) } -int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) +int Field_timestamp::cmp(const uchar *a_ptr, const uchar *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN @@ -4739,7 +4716,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) } -void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) +void Field_timestamp::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table || !table->s->db_low_byte_first) @@ -4940,7 +4917,7 @@ String *Field_time::val_str(String *val_buffer, { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - val_buffer->alloc(19); + val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH); long tmp=(long) sint3korr(ptr); ltime.neg= 0; if (tmp < 0) @@ -5021,7 +4998,7 @@ bool Field_time::send_binary(Protocol *protocol) } -int Field_time::cmp(const char *a_ptr, const char *b_ptr) +int Field_time::cmp(const uchar *a_ptr, const uchar *b_ptr) { int32 a,b; a=(int32) sint3korr(a_ptr); @@ -5029,7 +5006,7 @@ int Field_time::cmp(const char *a_ptr, const char *b_ptr) return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_time::sort_string(char *to,uint length __attribute__((unused))) +void Field_time::sort_string(uchar *to,uint length __attribute__((unused))) { to[0] = (uchar) (ptr[2] ^ 128); to[1] = ptr[1]; @@ -5133,7 +5110,7 @@ double Field_year::val_real(void) longlong Field_year::val_int(void) { ASSERT_COLUMN_MARKED_FOR_READ; - int tmp= (int) ((uchar*) ptr)[0]; + int tmp= (int) ptr[0]; if (field_length != 4) tmp%=100; // Return last 2 char else if (tmp) @@ -5327,7 +5304,7 @@ String *Field_date::val_str(String *val_buffer, } -int Field_date::cmp(const char *a_ptr, const char *b_ptr) +int Field_date::cmp(const uchar *a_ptr, const uchar *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN @@ -5346,7 +5323,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr) } -void Field_date::sort_string(char *to,uint length __attribute__((unused))) +void Field_date::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table || !table->s->db_low_byte_first) @@ -5488,7 +5465,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime,timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { - char buff[12]; + char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_date((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, @@ -5578,7 +5555,7 @@ bool Field_newdate::get_time(MYSQL_TIME *ltime) } -int Field_newdate::cmp(const char *a_ptr, const char *b_ptr) +int Field_newdate::cmp(const uchar *a_ptr, const uchar *b_ptr) { uint32 a,b; a=(uint32) uint3korr(a_ptr); @@ -5587,7 +5564,7 @@ int Field_newdate::cmp(const char *a_ptr, const char *b_ptr) } -void Field_newdate::sort_string(char *to,uint length __attribute__((unused))) +void Field_newdate::sort_string(uchar *to,uint length __attribute__((unused))) { to[0] = ptr[2]; to[1] = ptr[1]; @@ -5719,7 +5696,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { - char buff[19]; + char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, @@ -5795,7 +5772,7 @@ String *Field_datetime::val_str(String *val_buffer, part1=(long) (tmp/LL(1000000)); part2=(long) (tmp - (ulonglong) part1*LL(1000000)); - pos=(char*) val_buffer->ptr()+19; + pos=(char*) val_buffer->ptr() + MAX_DATETIME_WIDTH; *pos--=0; *pos--= (char) ('0'+(char) (part2%10)); part2/=10; *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10); @@ -5843,7 +5820,7 @@ bool Field_datetime::get_time(MYSQL_TIME *ltime) return Field_datetime::get_date(ltime,0); } -int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) +int Field_datetime::cmp(const uchar *a_ptr, const uchar *b_ptr) { longlong a,b; #ifdef WORDS_BIGENDIAN @@ -5862,7 +5839,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) ((ulonglong) a > (ulonglong) b) ? 1 : 0; } -void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) +void Field_datetime::sort_string(uchar *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN if (!table || !table->s->db_low_byte_first) @@ -5911,6 +5888,7 @@ void Field_datetime::sql_type(String &res) const well_formed_error_pos - where not well formed data was first met cannot_convert_error_pos - where a not-convertable character was first met end - end of the string + cs - character set of the string NOTES As of version 5.0 both cases return the same error: @@ -5930,7 +5908,8 @@ static bool check_string_copy_error(Field_str *field, const char *well_formed_error_pos, const char *cannot_convert_error_pos, - const char *end) + const char *end, + CHARSET_INFO *cs) { const char *pos, *end_orig; char tmp[64], *t; @@ -5944,8 +5923,18 @@ check_string_copy_error(Field_str *field, for (t= tmp; pos < end; pos++) { + /* + If the source string is ASCII compatible (mbminlen==1) + and the source character is in ASCII printable range (0x20..0x7F), + then display the character as is. + + Otherwise, if the source string is not ASCII compatible (e.g. UCS2), + or the source character is not in the printable range, + then print the character using HEX notation. + */ if (((unsigned char) *pos) >= 0x20 && - ((unsigned char) *pos) <= 0x7F) + ((unsigned char) *pos) <= 0x7F && + cs->mbminlen == 1) { *t++= *pos; } @@ -6013,7 +6002,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) DBUG_ASSERT(table->in_use == current_thd); copy_length= well_formed_copy_nchars(field_charset, - ptr, field_length, + (char*) ptr, field_length, cs, from, length, field_length / field_charset->mbmaxlen, &well_formed_error_pos, @@ -6022,12 +6011,12 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) /* Append spaces if the string was shorter than the field. */ if (copy_length < field_length) - field_charset->cset->fill(field_charset,ptr+copy_length, + field_charset->cset->fill(field_charset,(char*) ptr+copy_length, field_length-copy_length, field_charset->pad_char); if (check_string_copy_error(this, well_formed_error_pos, - cannot_convert_error_pos, from + length)) + cannot_convert_error_pos, from + length, cs)) return 2; /* @@ -6089,11 +6078,11 @@ int Field_str::store(double nr) like inserting 500.0 in char(1) */ DBUG_ASSERT(local_char_length < 5 || length <= local_char_length+1); - return store((const char *) buff, length, charset()); + return store(buff, length, charset()); } -uint Field::is_equal(create_field *new_field) +uint Field::is_equal(Create_field *new_field) { return (new_field->sql_type == real_type()); } @@ -6101,7 +6090,7 @@ uint Field::is_equal(create_field *new_field) /* If one of the fields is binary and the other one isn't return 1 else 0 */ -bool Field_str::compare_str_field_flags(create_field *new_field, uint32 flags) +bool Field_str::compare_str_field_flags(Create_field *new_field, uint32 flags) { return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) && !(flags & (BINCMP_FLAG | BINARY_FLAG))) || @@ -6110,7 +6099,7 @@ bool Field_str::compare_str_field_flags(create_field *new_field, uint32 flags) } -uint Field_str::is_equal(create_field *new_field) +uint Field_str::is_equal(Create_field *new_field) { if (compare_str_field_flags(new_field, flags)) return 0; @@ -6149,14 +6138,15 @@ double Field_string::val_real(void) CHARSET_INFO *cs= charset(); double result; - result= my_strntod(cs,ptr,field_length,&end,&error); + result= my_strntod(cs,(char*) ptr,field_length,&end,&error); if (!table->in_use->no_errors && - (error || (field_length != (uint32)(end - ptr) && - !check_if_only_end_space(cs, end, ptr + field_length)))) + (error || (field_length != (uint32)(end - (char*) ptr) && + !check_if_only_end_space(cs, end, + (char*) ptr + field_length)))) { char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; String tmp(buf, sizeof(buf), cs); - tmp.copy(ptr, field_length, cs); + tmp.copy((char*) ptr, field_length, cs); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), @@ -6174,14 +6164,15 @@ longlong Field_string::val_int(void) CHARSET_INFO *cs= charset(); longlong result; - result= my_strntoll(cs,ptr,field_length,10,&end,&error); + result= my_strntoll(cs, (char*) ptr,field_length,10,&end,&error); if (!table->in_use->no_errors && - (error || (field_length != (uint32)(end - ptr) && - !check_if_only_end_space(cs, end, ptr + field_length)))) + (error || (field_length != (uint32)(end - (char*) ptr) && + !check_if_only_end_space(cs, end, + (char*) ptr + field_length)))) { char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE]; String tmp(buf, sizeof(buf), cs); - tmp.copy(ptr, field_length, cs); + tmp.copy((char*) ptr, field_length, cs); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), @@ -6195,9 +6186,15 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { ASSERT_COLUMN_MARKED_FOR_READ; - uint length= field_charset->cset->lengthsp(field_charset, ptr, field_length); /* See the comment for Field_long::store(long long) */ DBUG_ASSERT(table->in_use == current_thd); + uint length; + if (table->in_use->variables.sql_mode & + MODE_PAD_CHAR_TO_FULL_LENGTH) + length= my_charpos(field_charset, ptr, ptr + field_length, field_length); + else + length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, + field_length); val_ptr->set((const char*) ptr, length, field_charset); return val_ptr; } @@ -6206,14 +6203,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), my_decimal *Field_string::val_decimal(my_decimal *decimal_value) { ASSERT_COLUMN_MARKED_FOR_READ; - int err= str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(), - decimal_value); + int err= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr, field_length, + charset(), decimal_value); if (!table->in_use->no_errors && err) { char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE]; CHARSET_INFO *cs= charset(); String tmp(buf, sizeof(buf), cs); - tmp.copy(ptr, field_length, cs); + tmp.copy((char*) ptr, field_length, cs); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), @@ -6224,7 +6221,7 @@ my_decimal *Field_string::val_decimal(my_decimal *decimal_value) } -int Field_string::cmp(const char *a_ptr, const char *b_ptr) +int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) { uint a_len, b_len; @@ -6241,17 +6238,17 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) like in latin_de 'ae' and 0xe4 */ return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a_ptr, a_len, - (const uchar*) b_ptr, b_len, + a_ptr, a_len, + b_ptr, b_len, 0); } -void Field_string::sort_string(char *to,uint length) +void Field_string::sort_string(uchar *to,uint length) { IF_DBUG(uint tmp=) my_strnxfrm(field_charset, - (uchar*) to, length, - (uchar*) ptr, field_length); + to, length, + ptr, field_length); DBUG_ASSERT(tmp == length); } @@ -6276,7 +6273,7 @@ void Field_string::sql_type(String &res) const } -char *Field_string::pack(char *to, const char *from, uint max_length) +uchar *Field_string::pack(uchar *to, const uchar *from, uint max_length) { uint length= min(field_length,max_length); uint local_char_length= max_length/field_charset->mbmaxlen; @@ -6286,15 +6283,15 @@ char *Field_string::pack(char *to, const char *from, uint max_length) set_if_smaller(length, local_char_length); while (length && from[length-1] == ' ') length--; - *to++= (char) (uchar) length; + *to++= (uchar) length; if (field_length > 255) - *to++= (char) (uchar) (length >> 8); + *to++= (uchar) (length >> 8); memcpy(to, from, length); return to+length; } -const char *Field_string::unpack(char *to, const char *from) +const uchar *Field_string::unpack(uchar *to, const uchar *from) { uint length; if (field_length > 255) @@ -6303,7 +6300,7 @@ const char *Field_string::unpack(char *to, const char *from) from+= 2; } else - length= (uint) (uchar) *from++; + length= (uint) *from++; memcpy(to, from, (int) length); bfill(to+length, field_length - length, ' '); return from+length; @@ -6326,7 +6323,7 @@ const char *Field_string::unpack(char *to, const char *from) > 0 a > b */ -int Field_string::pack_cmp(const char *a, const char *b, uint length, +int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length, my_bool insert_or_update) { uint a_length, b_length; @@ -6339,12 +6336,12 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length, } else { - a_length= (uint) (uchar) *a++; - b_length= (uint) (uchar) *b++; + a_length= (uint) *a++; + b_length= (uint) *b++; } return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a, a_length, - (const uchar*) b, b_length, + a, a_length, + b, b_length, insert_or_update); } @@ -6364,18 +6361,18 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length, > 0 row > key */ -int Field_string::pack_cmp(const char *key, uint length, +int Field_string::pack_cmp(const uchar *key, uint length, my_bool insert_or_update) { uint row_length, local_key_length; - char *end; + uchar *end; if (length > 255) { local_key_length= uint2korr(key); key+= 2; } else - local_key_length= (uint) (uchar) *key++; + local_key_length= (uint) *key++; /* Only use 'length' of key, not field_length */ end= ptr + length; @@ -6384,17 +6381,17 @@ int Field_string::pack_cmp(const char *key, uint length, row_length= (uint) (end - ptr); return field_charset->coll->strnncollsp(field_charset, - (const uchar*) ptr, row_length, - (const uchar*) key, local_key_length, + ptr, row_length, + key, local_key_length, insert_or_update); } -uint Field_string::packed_col_length(const char *data_ptr, uint length) +uint Field_string::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) return uint2korr(data_ptr)+2; - return (uint) ((uchar) *data_ptr)+1; + return (uint) *data_ptr + 1; } @@ -6403,16 +6400,20 @@ uint Field_string::max_packed_col_length(uint max_length) return (max_length > 255 ? 2 : 1)+max_length; } -uint Field_string::get_key_image(char *buff, uint length, imagetype type_arg) + +uint Field_string::get_key_image(uchar *buff, uint length, imagetype type_arg) { - uint bytes = my_charpos(field_charset, ptr, ptr + field_length, + uint bytes = my_charpos(field_charset, (char*) ptr, + (char*) ptr + field_length, length / field_charset->mbmaxlen); memcpy(buff, ptr, bytes); if (bytes < length) - bzero(buff + bytes, length - bytes); + field_charset->cset->fill(field_charset, (char*) buff + bytes, + length - bytes, field_charset->pad_char); return bytes; } + Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type) { @@ -6466,7 +6467,8 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) const char *from_end_pos; copy_length= well_formed_copy_nchars(field_charset, - ptr + length_bytes, field_length, + (char*) ptr + length_bytes, + field_length, cs, from, length, field_length / field_charset->mbmaxlen, &well_formed_error_pos, @@ -6479,7 +6481,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) int2store(ptr, copy_length); if (check_string_copy_error(this, well_formed_error_pos, - cannot_convert_error_pos, from + length)) + cannot_convert_error_pos, from + length, cs)) return 2; // Check if we lost something other than just trailing spaces @@ -6514,9 +6516,9 @@ double Field_varstring::val_real(void) ASSERT_COLUMN_MARKED_FOR_READ; int not_used; char *end_not_used; - uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); - return my_strntod(field_charset, ptr+length_bytes, length, &end_not_used, - ¬_used); + uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); + return my_strntod(field_charset, (char*) ptr+length_bytes, length, + &end_not_used, ¬_used); } @@ -6525,8 +6527,8 @@ longlong Field_varstring::val_int(void) ASSERT_COLUMN_MARKED_FOR_READ; int not_used; char *end_not_used; - uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); - return my_strntoll(field_charset, ptr+length_bytes, length, 10, + uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); + return my_strntoll(field_charset, (char*) ptr+length_bytes, length, 10, &end_not_used, ¬_used); } @@ -6534,7 +6536,7 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { ASSERT_COLUMN_MARKED_FOR_READ; - uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); val_ptr->set((const char*) ptr+length_bytes, length, field_charset); return val_ptr; } @@ -6543,14 +6545,14 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)), my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value) { ASSERT_COLUMN_MARKED_FOR_READ; - uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); - str2my_decimal(E_DEC_FATAL_ERROR, ptr+length_bytes, length, charset(), - decimal_value); + uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); + str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length, + charset(), decimal_value); return decimal_value; } -int Field_varstring::cmp_max(const char *a_ptr, const char *b_ptr, +int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr, uint max_len) { uint a_length, b_length; @@ -6558,8 +6560,8 @@ int Field_varstring::cmp_max(const char *a_ptr, const char *b_ptr, if (length_bytes == 1) { - a_length= (uint) (uchar) *a_ptr; - b_length= (uint) (uchar) *b_ptr; + a_length= (uint) *a_ptr; + b_length= (uint) *b_ptr; } else { @@ -6569,10 +6571,10 @@ int Field_varstring::cmp_max(const char *a_ptr, const char *b_ptr, set_if_smaller(a_length, max_len); set_if_smaller(b_length, max_len); diff= field_charset->coll->strnncollsp(field_charset, - (const uchar*) a_ptr+ + a_ptr+ length_bytes, a_length, - (const uchar*) b_ptr+ + b_ptr+ length_bytes, b_length,0); return diff; @@ -6583,18 +6585,18 @@ int Field_varstring::cmp_max(const char *a_ptr, const char *b_ptr, NOTE: varstring and blob keys are ALWAYS stored with a 2 byte length prefix */ -int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length) +int Field_varstring::key_cmp(const uchar *key_ptr, uint max_key_length) { - uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); uint local_char_length= max_key_length / field_charset->mbmaxlen; local_char_length= my_charpos(field_charset, ptr + length_bytes, ptr + length_bytes + length, local_char_length); set_if_smaller(length, local_char_length); return field_charset->coll->strnncollsp(field_charset, - (const uchar*) ptr + length_bytes, + ptr + length_bytes, length, - (const uchar*) key_ptr+ + key_ptr+ HA_KEY_BLOB_LENGTH, uint2korr(key_ptr), 0); } @@ -6608,22 +6610,20 @@ int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length) (keys are created and compared in key.cc) */ -int Field_varstring::key_cmp(const byte *a,const byte *b) +int Field_varstring::key_cmp(const uchar *a,const uchar *b) { return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a + - HA_KEY_BLOB_LENGTH, + a + HA_KEY_BLOB_LENGTH, uint2korr(a), - (const uchar*) b + - HA_KEY_BLOB_LENGTH, + b + HA_KEY_BLOB_LENGTH, uint2korr(b), 0); } -void Field_varstring::sort_string(char *to,uint length) +void Field_varstring::sort_string(uchar *to,uint length) { - uint tot_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uint tot_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); if (field_charset == &my_charset_bin) { @@ -6636,8 +6636,7 @@ void Field_varstring::sort_string(char *to,uint length) } tot_length= my_strnxfrm(field_charset, - (uchar*) to, length, - (uchar*) ptr + length_bytes, + to, length, ptr + length_bytes, tot_length); DBUG_ASSERT(tot_length == length); } @@ -6674,7 +6673,7 @@ void Field_varstring::sql_type(String &res) const uint32 Field_varstring::data_length() { - return length_bytes == 1 ? (uint32) (uchar) *ptr : uint2korr(ptr); + return length_bytes == 1 ? (uint32) *ptr : uint2korr(ptr); } /* @@ -6682,9 +6681,9 @@ uint32 Field_varstring::data_length() Here the number of length bytes are depending on the given max_length */ -char *Field_varstring::pack(char *to, const char *from, uint max_length) +uchar *Field_varstring::pack(uchar *to, const uchar *from, uint max_length) { - uint length= length_bytes == 1 ? (uint) (uchar) *from : uint2korr(from); + uint length= length_bytes == 1 ? (uint) *from : uint2korr(from); set_if_smaller(max_length, field_length); if (length > max_length) length=max_length; @@ -6697,9 +6696,9 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length) } -char *Field_varstring::pack_key(char *to, const char *key, uint max_length) +uchar *Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length) { - uint length= length_bytes == 1 ? (uint) (uchar) *key : uint2korr(key); + uint length= length_bytes == 1 ? (uint) *key : uint2korr(key); uint local_char_length= ((field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length); key+= length_bytes; @@ -6736,13 +6735,13 @@ char *Field_varstring::pack_key(char *to, const char *key, uint max_length) Pointer to end of 'key' (To the next key part if multi-segment key) */ -const char *Field_varstring::unpack_key(char *to, const char *key, - uint max_length) +const uchar *Field_varstring::unpack_key(uchar *to, const uchar *key, + uint max_length) { /* get length of the blob key */ - uint32 length= *((uchar*) key++); + uint32 length= *key++; if (max_length > 255) - length+= (*((uchar*) key++)) << 8; + length+= (*key++) << 8; /* put the length into the record buffer */ if (length_bytes == 1) @@ -6766,8 +6765,8 @@ const char *Field_varstring::unpack_key(char *to, const char *key, end of key storage */ -char *Field_varstring::pack_key_from_key_image(char *to, const char *from, - uint max_length) +uchar *Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, + uint max_length) { /* Key length is always stored as 2 bytes */ uint length= uint2korr(from); @@ -6786,11 +6785,11 @@ char *Field_varstring::pack_key_from_key_image(char *to, const char *from, unpack field packed with Field_varstring::pack() */ -const char *Field_varstring::unpack(char *to, const char *from) +const uchar *Field_varstring::unpack(uchar *to, const uchar *from) { uint length; if (length_bytes == 1) - length= (uint) (uchar) (*to= *from++); + length= (uint) (*to= *from++); else { length= uint2korr(from); @@ -6803,7 +6802,7 @@ const char *Field_varstring::unpack(char *to, const char *from) } -int Field_varstring::pack_cmp(const char *a, const char *b, +int Field_varstring::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg, my_bool insert_or_update) { @@ -6815,21 +6814,21 @@ int Field_varstring::pack_cmp(const char *a, const char *b, } else { - a_length= (uint) (uchar) *a++; - b_length= (uint) (uchar) *b++; + a_length= (uint) *a++; + b_length= (uint) *b++; } return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a, a_length, - (const uchar*) b, b_length, + a, a_length, + b, b_length, insert_or_update); } -int Field_varstring::pack_cmp(const char *b, uint key_length_arg, +int Field_varstring::pack_cmp(const uchar *b, uint key_length_arg, my_bool insert_or_update) { - char *a= ptr+ length_bytes; - uint a_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uchar *a= ptr+ length_bytes; + uint a_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); uint b_length; uint local_char_length= ((field_charset->mbmaxlen > 1) ? key_length_arg / field_charset->mbmaxlen : @@ -6840,7 +6839,7 @@ int Field_varstring::pack_cmp(const char *b, uint key_length_arg, b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH; } else - b_length= (uint) (uchar) *b++; + b_length= (uint) *b++; if (a_length > local_char_length) { @@ -6850,18 +6849,17 @@ int Field_varstring::pack_cmp(const char *b, uint key_length_arg, } return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a, - a_length, - (const uchar*) b, b_length, + a, a_length, + b, b_length, insert_or_update); } -uint Field_varstring::packed_col_length(const char *data_ptr, uint length) +uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) return uint2korr(data_ptr)+2; - return (uint) ((uchar) *data_ptr)+1; + return (uint) *data_ptr + 1; } @@ -6870,11 +6868,11 @@ uint Field_varstring::max_packed_col_length(uint max_length) return (max_length > 255 ? 2 : 1)+max_length; } -uint Field_varstring::get_key_image(char *buff, uint length, imagetype type) +uint Field_varstring::get_key_image(uchar *buff, uint length, imagetype type) { - uint f_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uint f_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); uint local_char_length= length / field_charset->mbmaxlen; - char *pos= ptr+length_bytes; + uchar *pos= ptr+length_bytes; local_char_length= my_charpos(field_charset, pos, pos + f_length, local_char_length); set_if_smaller(f_length, local_char_length); @@ -6893,23 +6891,23 @@ uint Field_varstring::get_key_image(char *buff, uint length, imagetype type) } -void Field_varstring::set_key_image(char *buff,uint length) +void Field_varstring::set_key_image(const uchar *buff,uint length) { length= uint2korr(buff); // Real length is here - (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, + (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset); } -int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr, +int Field_varstring::cmp_binary(const uchar *a_ptr, const uchar *b_ptr, uint32 max_length) { uint32 a_length,b_length; if (length_bytes == 1) { - a_length= (uint) (uchar) *a_ptr; - b_length= (uint) (uchar) *b_ptr; + a_length= (uint) *a_ptr; + b_length= (uint) *b_ptr; } else { @@ -6937,7 +6935,7 @@ Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table, Field *Field_varstring::new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit) { Field_varstring *res; @@ -6954,7 +6952,7 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, } -uint Field_varstring::is_equal(create_field *new_field) +uint Field_varstring::is_equal(Create_field *new_field) { if (new_field->sql_type == real_type() && new_field->charset == field_charset) @@ -6978,9 +6976,9 @@ void Field_varstring::hash(ulong *nr, ulong *nr2) } else { - uint len= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + uint len= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); CHARSET_INFO *cs= charset(); - cs->coll->hash_sort(cs, (uchar*) ptr + length_bytes, len, nr, nr2); + cs->coll->hash_sort(cs, ptr + length_bytes, len, nr, nr2); } } @@ -6991,7 +6989,7 @@ void Field_varstring::hash(ulong *nr, ulong *nr2) ** packlength slot and may be from 1-4. ****************************************************************************/ -Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, +Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs) @@ -7006,7 +7004,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, } -void Field_blob::store_length(char *i_ptr, uint i_packlength, uint32 i_number) +void Field_blob::store_length(uchar *i_ptr, uint i_packlength, uint32 i_number) { switch (i_packlength) { case 1: @@ -7038,11 +7036,11 @@ void Field_blob::store_length(char *i_ptr, uint i_packlength, uint32 i_number) } -uint32 Field_blob::get_length(const char *pos) +uint32 Field_blob::get_length(const uchar *pos) { switch (packlength) { case 1: - return (uint32) (uchar) pos[0]; + return (uint32) pos[0]; case 2: { uint16 tmp; @@ -7089,7 +7087,7 @@ uint32 Field_blob::get_length(const char *pos) nothing */ -void Field_blob::put_length(char *pos, uint32 length) +void Field_blob::put_length(uchar *pos, uint32 length) { switch (packlength) { case 1: @@ -7157,10 +7155,10 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) Field_blob::store_length(copy_length); tmp= value.ptr(); - bmove(ptr+packlength,(char*) &tmp,sizeof(char*)); + bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*)); if (check_string_copy_error(this, well_formed_error_pos, - cannot_convert_error_pos, from + length)) + cannot_convert_error_pos, from + length, cs)) return 2; if (from_end_pos < from + length) @@ -7241,29 +7239,35 @@ my_decimal *Field_blob::val_decimal(my_decimal *decimal_value) { ASSERT_COLUMN_MARKED_FOR_READ; const char *blob; - memcpy_fixed(&blob, ptr+packlength, sizeof(const char*)); + size_t length; + memcpy_fixed(&blob, ptr+packlength, sizeof(const uchar*)); if (!blob) + { blob= ""; - str2my_decimal(E_DEC_FATAL_ERROR, blob, get_length(ptr), charset(), + length= 0; + } + else + length= get_length(ptr); + + str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(), decimal_value); return decimal_value; } -int Field_blob::cmp(const char *a,uint32 a_length, const char *b, +int Field_blob::cmp(const uchar *a,uint32 a_length, const uchar *b, uint32 b_length) { return field_charset->coll->strnncollsp(field_charset, - (const uchar*)a, a_length, - (const uchar*)b, b_length, + a, a_length, b, b_length, 0); } -int Field_blob::cmp_max(const char *a_ptr, const char *b_ptr, +int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr, uint max_length) { - char *blob1,*blob2; + uchar *blob1,*blob2; memcpy_fixed(&blob1,a_ptr+packlength,sizeof(char*)); memcpy_fixed(&blob2,b_ptr+packlength,sizeof(char*)); uint a_len= get_length(a_ptr), b_len= get_length(b_ptr); @@ -7273,7 +7277,7 @@ int Field_blob::cmp_max(const char *a_ptr, const char *b_ptr, } -int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr, +int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr, uint32 max_length) { char *a,*b; @@ -7294,10 +7298,10 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr, /* The following is used only when comparing a key */ -uint Field_blob::get_key_image(char *buff,uint length, imagetype type_arg) +uint Field_blob::get_key_image(uchar *buff,uint length, imagetype type_arg) { uint32 blob_length= get_length(ptr); - char *blob; + uchar *blob; #ifdef HAVE_SPATIAL if (type_arg == itMBR) @@ -7314,7 +7318,7 @@ uint Field_blob::get_key_image(char *buff,uint length, imagetype type_arg) return image_length; } get_ptr(&blob); - gobj= Geometry::construct(&buffer, blob, blob_length); + gobj= Geometry::construct(&buffer, (char*) blob, blob_length); if (!gobj || gobj->get_mbr(&mbr, &dummy)) bzero(buff, image_length); else @@ -7349,16 +7353,17 @@ uint Field_blob::get_key_image(char *buff,uint length, imagetype type_arg) } -void Field_blob::set_key_image(char *buff,uint length) +void Field_blob::set_key_image(const uchar *buff,uint length) { length= uint2korr(buff); - (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, field_charset); + (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, + field_charset); } -int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length) +int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length) { - char *blob1; + uchar *blob1; uint blob_length=get_length(ptr); memcpy_fixed(&blob1,ptr+packlength,sizeof(char*)); CHARSET_INFO *cs= charset(); @@ -7367,14 +7372,14 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length) local_char_length); set_if_smaller(blob_length, local_char_length); return Field_blob::cmp(blob1, blob_length, - (char*) key_ptr+HA_KEY_BLOB_LENGTH, + key_ptr+HA_KEY_BLOB_LENGTH, uint2korr(key_ptr)); } -int Field_blob::key_cmp(const byte *a,const byte *b) +int Field_blob::key_cmp(const uchar *a,const uchar *b) { - return Field_blob::cmp((char*) a+HA_KEY_BLOB_LENGTH, uint2korr(a), - (char*) b+HA_KEY_BLOB_LENGTH, uint2korr(b)); + return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a), + b+HA_KEY_BLOB_LENGTH, uint2korr(b)); } @@ -7385,9 +7390,9 @@ uint32 Field_blob::sort_length() const } -void Field_blob::sort_string(char *to,uint length) +void Field_blob::sort_string(uchar *to,uint length) { - char *blob; + uchar *blob; uint blob_length=get_length(); if (!blob_length) @@ -7396,7 +7401,7 @@ void Field_blob::sort_string(char *to,uint length) { if (field_charset == &my_charset_bin) { - char *pos; + uchar *pos; /* Store length of blob last in blob to shorter blobs before longer blobs @@ -7422,8 +7427,7 @@ void Field_blob::sort_string(char *to,uint length) memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); blob_length=my_strnxfrm(field_charset, - (uchar*) to, length, - (uchar*) blob, blob_length); + to, length, blob, blob_length); DBUG_ASSERT(blob_length == length); } } @@ -7449,23 +7453,23 @@ void Field_blob::sql_type(String &res) const } -char *Field_blob::pack(char *to, const char *from, uint max_length) +uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length) { - char *save=ptr; - ptr=(char*) from; + uchar *save= ptr; + ptr= (uchar*) from; uint32 length=get_length(); // Length of from string if (length > max_length) { ptr=to; length=max_length; store_length(length); // Store max length - ptr=(char*) from; + ptr= (uchar*) from; } else memcpy(to,from,packlength); // Copy length if (length) { - get_ptr((char**) &from); + get_ptr((uchar**) &from); memcpy(to+packlength, from,length); } ptr=save; // Restore org row pointer @@ -7473,7 +7477,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length) } -const char *Field_blob::unpack(char *to, const char *from) +const uchar *Field_blob::unpack(uchar *to, const uchar *from) { memcpy(to,from,packlength); uint32 length=get_length(from); @@ -7487,7 +7491,7 @@ const char *Field_blob::unpack(char *to, const char *from) /* Keys for blobs are like keys on varchars */ -int Field_blob::pack_cmp(const char *a, const char *b, uint key_length_arg, +int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg, my_bool insert_or_update) { uint a_length, b_length; @@ -7498,20 +7502,20 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length_arg, } else { - a_length= (uint) (uchar) *a++; - b_length= (uint) (uchar) *b++; + a_length= (uint) *a++; + b_length= (uint) *b++; } return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a, a_length, - (const uchar*) b, b_length, + a, a_length, + b, b_length, insert_or_update); } -int Field_blob::pack_cmp(const char *b, uint key_length_arg, +int Field_blob::pack_cmp(const uchar *b, uint key_length_arg, my_bool insert_or_update) { - char *a; + uchar *a; uint a_length, b_length; memcpy_fixed(&a,ptr+packlength,sizeof(char*)); if (!a) @@ -7523,24 +7527,24 @@ int Field_blob::pack_cmp(const char *b, uint key_length_arg, b_length= uint2korr(b); b+=2; } else - b_length= (uint) (uchar) *b++; + b_length= (uint) *b++; return field_charset->coll->strnncollsp(field_charset, - (const uchar*) a, a_length, - (const uchar*) b, b_length, + a, a_length, + b, b_length, insert_or_update); } /* Create a packed key that will be used for storage from a MySQL row */ -char *Field_blob::pack_key(char *to, const char *from, uint max_length) +uchar *Field_blob::pack_key(uchar *to, const uchar *from, uint max_length) { - char *save=ptr; - ptr=(char*) from; + uchar *save= ptr; + ptr= (uchar*) from; uint32 length=get_length(); // Length of from string uint local_char_length= ((field_charset->mbmaxlen > 1) ? - max_length/field_charset->mbmaxlen : max_length); + max_length/field_charset->mbmaxlen : max_length); if (length) - get_ptr((char**) &from); + get_ptr((uchar**) &from); if (length > local_char_length) local_char_length= my_charpos(field_charset, from, from+length, local_char_length); @@ -7577,12 +7581,13 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) Pointer into 'from' past the last byte copied from packed key. */ -const char *Field_blob::unpack_key(char *to, const char *from, uint max_length) +const uchar *Field_blob::unpack_key(uchar *to, const uchar *from, + uint max_length) { /* get length of the blob key */ - uint32 length= *((uchar*) from++); + uint32 length= *from++; if (max_length > 255) - length+= (*((uchar*) from++)) << 8; + length+= *from++ << 8; /* put the length into the record buffer */ put_length(to, length); @@ -7600,8 +7605,8 @@ const char *Field_blob::unpack_key(char *to, const char *from, uint max_length) /* Create a packed key that will be used for storage from a MySQL key */ -char *Field_blob::pack_key_from_key_image(char *to, const char *from, - uint max_length) +uchar *Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, + uint max_length) { uint length=uint2korr(from); if (length > max_length) @@ -7615,11 +7620,11 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from, } -uint Field_blob::packed_col_length(const char *data_ptr, uint length) +uint Field_blob::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) return uint2korr(data_ptr)+2; - return (uint) ((uchar) *data_ptr)+1; + return (uint) *data_ptr + 1; } @@ -7629,7 +7634,7 @@ uint Field_blob::max_packed_col_length(uint max_length) } -uint Field_blob::is_equal(create_field *new_field) +uint Field_blob::is_equal(Create_field *new_field) { if (compare_str_field_flags(new_field, flags)) return 0; @@ -7643,9 +7648,9 @@ uint Field_blob::is_equal(create_field *new_field) #ifdef HAVE_SPATIAL -uint Field_geom::get_key_image(char *buff, uint length, imagetype type) +uint Field_geom::get_key_image(uchar *buff, uint length, imagetype type) { - char *blob; + uchar *blob; const char *dummy; MBR mbr; ulong blob_length= get_length(ptr); @@ -7659,7 +7664,7 @@ uint Field_geom::get_key_image(char *buff, uint length, imagetype type) return image_length; } get_ptr(&blob); - gobj= Geometry::construct(&buffer, blob, blob_length); + gobj= Geometry::construct(&buffer, (char*) blob, blob_length); if (!gobj || gobj->get_mbr(&mbr, &dummy)) bzero(buff, image_length); else @@ -7856,6 +7861,8 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) tmp=0; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } + if (!table->in_use->count_cuted_fields) + err= 0; } else set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); @@ -7897,7 +7904,7 @@ longlong Field_enum::val_int(void) ASSERT_COLUMN_MARKED_FOR_READ; switch (packlength) { case 1: - return (longlong) (uchar) ptr[0]; + return (longlong) ptr[0]; case 2: { uint16 tmp; @@ -7951,18 +7958,18 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)), return val_ptr; } -int Field_enum::cmp(const char *a_ptr, const char *b_ptr) +int Field_enum::cmp(const uchar *a_ptr, const uchar *b_ptr) { - char *old=ptr; - ptr=(char*) a_ptr; + uchar *old= ptr; + ptr= (uchar*) a_ptr; ulonglong a=Field_enum::val_int(); - ptr=(char*) b_ptr; + ptr= (uchar*) b_ptr; ulonglong b=Field_enum::val_int(); - ptr=old; + ptr= old; return (a < b) ? -1 : (a > b) ? 1 : 0; } -void Field_enum::sort_string(char *to,uint length __attribute__((unused))) +void Field_enum::sort_string(uchar *to,uint length __attribute__((unused))) { ulonglong value=Field_enum::val_int(); to+=packlength-1; @@ -8144,9 +8151,9 @@ bool Field_enum::eq_def(Field *field) for (uint i=0 ; i < from_lib->count ; i++) if (my_strnncoll(field_charset, (const uchar*)typelib->type_names[i], - (uint) strlen(typelib->type_names[i]), + strlen(typelib->type_names[i]), (const uchar*)from_lib->type_names[i], - (uint) strlen(from_lib->type_names[i]))) + strlen(from_lib->type_names[i]))) return 0; return 1; } @@ -8165,7 +8172,7 @@ bool Field_num::eq_def(Field *field) } -uint Field_num::is_equal(create_field *new_field) +uint Field_num::is_equal(Create_field *new_field) { return ((new_field->sql_type == real_type()) && ((new_field->flags & UNSIGNED_FLAG) == (uint) (flags & @@ -8205,7 +8212,7 @@ uint Field_num::is_equal(create_field *new_field) 11 one byte for 'd' */ -Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, +Field_bit::Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, enum utype unireg_check_arg, const char *field_name_arg) : Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, @@ -8223,7 +8230,7 @@ Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, } -my_size_t +size_t Field_bit::do_last_null_byte() const { /* @@ -8245,14 +8252,14 @@ Field_bit::do_last_null_byte() const result= bit_ptr; if (result) - return (byte*) result - table->record[0] + 1; - else - return LAST_NULL_BYTE_UNDEF; + return (size_t) (result - table->record[0]) + 1; + return LAST_NULL_BYTE_UNDEF; } + Field *Field_bit::new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit) { Field_bit *res; @@ -8261,7 +8268,7 @@ Field *Field_bit::new_key_field(MEM_ROOT *root, new_null_bit))) { /* Move bits normally stored in null_pointer to new_ptr */ - res->bit_ptr= (uchar*) new_ptr; + res->bit_ptr= new_ptr; res->bit_ofs= 0; if (bit_len) res->ptr++; // Store rest of data here @@ -8270,6 +8277,13 @@ Field *Field_bit::new_key_field(MEM_ROOT *root, } +uint Field_bit::is_equal(Create_field *new_field) +{ + return (new_field->sql_type == real_type() && + new_field->length == max_display_length()); +} + + int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) { ASSERT_COLUMN_MARKED_FOR_WRITE; @@ -8358,7 +8372,7 @@ longlong Field_bit::val_int(void) switch (bytes_in_rec) { case 0: return bits; - case 1: return bits | (ulonglong) (uchar) ptr[0]; + case 1: return bits | (ulonglong) ptr[0]; case 2: return bits | mi_uint2korr(ptr); case 3: return bits | mi_uint3korr(ptr); case 4: return bits | mi_uint4korr(ptr); @@ -8408,7 +8422,7 @@ my_decimal *Field_bit::val_decimal(my_decimal *deciaml_value) The a and b pointer must be pointers to the field in a record (not the table->record[0] necessarily) */ -int Field_bit::cmp_max(const char *a, const char *b, uint max_len) +int Field_bit::cmp_max(const uchar *a, const uchar *b, uint max_len) { my_ptrdiff_t a_diff= a - ptr; my_ptrdiff_t b_diff= b - ptr; @@ -8424,13 +8438,13 @@ int Field_bit::cmp_max(const char *a, const char *b, uint max_len) } -int Field_bit::key_cmp(const byte *str, uint length) +int Field_bit::key_cmp(const uchar *str, uint length) { if (bit_len) { int flag; uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); - if ((flag= (int) (bits - *(uchar*) str))) + if ((flag= (int) (bits - *str))) return flag; str++; length--; @@ -8453,7 +8467,7 @@ int Field_bit::cmp_offset(uint row_offset) } -uint Field_bit::get_key_image(char *buff, uint length, imagetype type_arg) +uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg) { if (bit_len) { @@ -8476,7 +8490,7 @@ void Field_bit::sql_type(String &res) const } -char *Field_bit::pack(char *to, const char *from, uint max_length) +uchar *Field_bit::pack(uchar *to, const uchar *from, uint max_length) { DBUG_ASSERT(max_length); uint length; @@ -8510,7 +8524,7 @@ char *Field_bit::pack(char *to, const char *from, uint max_length) } -const char *Field_bit::unpack(char *to, const char *from) +const uchar *Field_bit::unpack(uchar *to, const uchar *from) { if (bit_len > 0) { @@ -8544,7 +8558,7 @@ void Field_bit::set_default() Bit field support for non-MyISAM tables. */ -Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, +Field_bit_as_char::Field_bit_as_char(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg) @@ -8571,7 +8585,7 @@ int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs) { memset(ptr, 0xff, bytes_in_rec); if (bits) - *ptr&= ((1 << bits) - 1); /* set first byte */ + *ptr&= ((1 << bits) - 1); /* set first uchar */ if (table->in_use->really_abort_on_warning()) set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); else @@ -8594,20 +8608,20 @@ void Field_bit_as_char::sql_type(String &res) const /***************************************************************************** - Handling of field and create_field + Handling of field and Create_field *****************************************************************************/ /* - Convert create_field::length from number of characters to number of bytes + Convert Create_field::length from number of characters to number of bytes SYNOPSIS - create_field::create_length_to_internal_length() + Create_field::create_length_to_internal_length() DESCRIPTION - Convert create_field::length from number of characters to number of bytes. + Convert Create_field::length from number of characters to number of bytes. */ -void create_field::create_length_to_internal_length(void) +void Create_field::create_length_to_internal_length(void) { switch (sql_type) { case MYSQL_TYPE_TINY_BLOB: @@ -8654,7 +8668,7 @@ void create_field::create_length_to_internal_length(void) } -void create_field::init_for_tmp_table(enum_field_types sql_type_arg, +void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, uint32 length_arg, uint32 decimals_arg, bool maybe_null, bool is_unsigned) { @@ -8695,7 +8709,7 @@ void create_field::init_for_tmp_table(enum_field_types sql_type_arg, TRUE on error */ -bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, +bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, char *fld_length, char *fld_decimals, uint fld_type_modifier, Item *fld_default_value, Item *fld_on_update_value, LEX_STRING *fld_comment, @@ -8705,7 +8719,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, uint sign_len, allowed_type_modifier= 0; ulong max_field_charlength= MAX_FIELD_CHARLENGTH; - DBUG_ENTER("create_field::init()"); + DBUG_ENTER("Create_field::init()"); field= 0; field_name= fld_name; @@ -8889,15 +8903,18 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, break; case MYSQL_TYPE_TIMESTAMP: if (!fld_length) - length= 14; /* Full date YYYYMMDDHHMMSS */ - else if (length != 19) + { + /* Compressed date YYYYMMDDHHMMSS */ + length= MAX_DATETIME_COMPRESSED_WIDTH; + } + else if (length != MAX_DATETIME_WIDTH) { /* We support only even TIMESTAMP lengths less or equal than 14 and 19 as length of 4.1 compatible representation. */ length= ((length+1)/2)*2; /* purecov: inspected */ - length= min(length,14); /* purecov: inspected */ + length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */ } flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; if (fld_default_value) @@ -8950,7 +8967,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, length= 10; break; case MYSQL_TYPE_DATETIME: - length= 19; + length= MAX_DATETIME_WIDTH; break; case MYSQL_TYPE_SET: { @@ -9098,7 +9115,7 @@ uint pack_length_to_packflag(uint type) } -Field *make_field(TABLE_SHARE *share, char *ptr, uint32 field_length, +Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length, uchar *null_pos, uchar null_bit, uint pack_flag, enum_field_types field_type, @@ -9278,7 +9295,7 @@ Field *make_field(TABLE_SHARE *share, char *ptr, uint32 field_length, /* Create a field suitable for create of table */ -create_field::create_field(Field *old_field,Field *orig_field) +Create_field::Create_field(Field *old_field,Field *orig_field) { field= old_field; field_name=change=old_field->field_name; diff --git a/sql/field.h b/sql/field.h index 2c2640a8262..a0fe0f2e57e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -28,7 +28,7 @@ class Send_field; class Protocol; -class create_field; +class Create_field; struct st_cache_field; int field_conv(Field *to,Field *from); @@ -48,10 +48,10 @@ class Field Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) {return sql_alloc(size); } static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } - char *ptr; // Position to field in record + uchar *ptr; // Position to field in record uchar *null_ptr; // Byte where null_bit is /* Note that you can use table->in_use as replacement for current_thd member @@ -90,11 +90,12 @@ public: uint16 field_index; // field number in fields array uchar null_bit; // Bit used to test null bit - Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg, - utype unireg_check_arg, const char *field_name_arg); + Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, + uchar null_bit_arg, utype unireg_check_arg, + const char *field_name_arg); virtual ~Field() {} /* Store functions returns 1 on overflow and -1 on fatal error */ - virtual int store(const char *to,uint length,CHARSET_INFO *cs)=0; + virtual int store(const char *to, uint length,CHARSET_INFO *cs)=0; virtual int store(double nr)=0; virtual int store(longlong nr, bool unsigned_val)=0; virtual int store_decimal(const my_decimal *d)=0; @@ -171,20 +172,20 @@ public: virtual uint32 key_length() const { return pack_length(); } virtual enum_field_types type() const =0; virtual enum_field_types real_type() const { return type(); } - inline int cmp(const char *str) { return cmp(ptr,str); } - virtual int cmp_max(const char *a, const char *b, uint max_len) + inline int cmp(const uchar *str) { return cmp(ptr,str); } + virtual int cmp_max(const uchar *a, const uchar *b, uint max_len) { return cmp(a, b); } - virtual int cmp(const char *,const char *)=0; - virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L) + virtual int cmp(const uchar *,const uchar *)=0; + virtual int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L) { return memcmp(a,b,pack_length()); } virtual int cmp_offset(uint row_offset) { return cmp(ptr,ptr+row_offset); } virtual int cmp_binary_offset(uint row_offset) { return cmp_binary(ptr, ptr+row_offset); }; - virtual int key_cmp(const byte *a,const byte *b) - { return cmp((char*) a,(char*) b); } - virtual int key_cmp(const byte *str, uint length) - { return cmp(ptr,(char*) str); } + virtual int key_cmp(const uchar *a,const uchar *b) + { return cmp(a, b); } + virtual int key_cmp(const uchar *str, uint length) + { return cmp(ptr,str); } virtual uint decimals() const { return 0; } /* Caller beware: sql_type can change str.Ptr, so check @@ -201,7 +202,7 @@ public: { if (!null_ptr) return 0; - return test(record[(uint) (null_ptr - (uchar*) table->record[0])] & + return test(record[(uint) (null_ptr -table->record[0])] & null_bit); } inline bool is_null_in_record_with_offset(my_ptrdiff_t offset) @@ -236,15 +237,15 @@ public: the record. If the field does not use any bits of the null bytes, the value 0 (LAST_NULL_BYTE_UNDEF) is returned. */ - my_size_t last_null_byte() const { - my_size_t bytes= do_last_null_byte(); + size_t last_null_byte() const { + size_t bytes= do_last_null_byte(); DBUG_PRINT("debug", ("last_null_byte() ==> %ld", (long) bytes)); DBUG_ASSERT(bytes <= table->s->null_bytes); return bytes; } virtual void make_field(Send_field *); - virtual void sort_string(char *buff,uint length)=0; + virtual void sort_string(uchar *buff,uint length)=0; virtual bool optimize_range(uint idx, uint part); /* This should be true for fields which, when compared with constant @@ -258,23 +259,23 @@ public: virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); Field *clone(MEM_ROOT *mem_root, struct st_table *new_table); - inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) + inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; } - inline void move_field(char *ptr_arg) { ptr=ptr_arg; } + inline void move_field(uchar *ptr_arg) { ptr=ptr_arg; } virtual void move_field_offset(my_ptrdiff_t ptr_diff) { - ptr=ADD_TO_PTR(ptr,ptr_diff,char*); + ptr=ADD_TO_PTR(ptr,ptr_diff, uchar*); if (null_ptr) null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*); } - inline void get_image(char *buff,uint length, CHARSET_INFO *cs) + inline void get_image(uchar *buff,uint length, CHARSET_INFO *cs) { memcpy(buff,ptr,length); } - inline void set_image(char *buff,uint length, CHARSET_INFO *cs) + inline void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) { memcpy(ptr,buff,length); } @@ -304,12 +305,12 @@ public: Number of copied bytes (excluding padded zero bytes -- see above). */ - virtual uint get_key_image(char *buff, uint length, imagetype type) + virtual uint get_key_image(uchar *buff, uint length, imagetype type) { get_image(buff, length, &my_charset_bin); return length; } - virtual void set_key_image(char *buff,uint length) + virtual void set_key_image(const uchar *buff,uint length) { set_image(buff,length, &my_charset_bin); } inline longlong val_int_offset(uint row_offset) { @@ -318,63 +319,64 @@ public: ptr-=row_offset; return tmp; } - inline longlong val_int(char *new_ptr) + inline longlong val_int(const uchar *new_ptr) { - char *old_ptr= ptr; + uchar *old_ptr= ptr; longlong return_value; - ptr= new_ptr; + ptr= (uchar*) new_ptr; return_value= val_int(); ptr= old_ptr; return return_value; } - inline String *val_str(String *str, char *new_ptr) + inline String *val_str(String *str, const uchar *new_ptr) { - char *old_ptr= ptr; - ptr= new_ptr; + uchar *old_ptr= ptr; + ptr= (uchar*) new_ptr; val_str(str); ptr= old_ptr; return str; } virtual bool send_binary(Protocol *protocol); - virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) + virtual uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0) { uint32 length=pack_length(); memcpy(to,from,length); return to+length; } - virtual const char *unpack(char* to, const char *from) + virtual const uchar *unpack(uchar* to, const uchar *from) { uint length=pack_length(); memcpy(to,from,length); return from+length; } - virtual char *pack_key(char* to, const char *from, uint max_length) + virtual uchar *pack_key(uchar* to, const uchar *from, uint max_length) { return pack(to,from,max_length); } - virtual char *pack_key_from_key_image(char* to, const char *from, + virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from, uint max_length) { return pack(to,from,max_length); } - virtual const char *unpack_key(char* to, const char *from, uint max_length) + virtual const uchar *unpack_key(uchar* to, const uchar *from, + uint max_length) { return unpack(to,from); } - virtual uint packed_col_length(const char *to, uint length) + virtual uint packed_col_length(const uchar *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) { return max_length;} - virtual int pack_cmp(const char *a,const char *b, uint key_length_arg, + virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg, my_bool insert_or_update) { return cmp(a,b); } - virtual int pack_cmp(const char *b, uint key_length_arg, + virtual int pack_cmp(const uchar *b, uint key_length_arg, my_bool insert_or_update) { return cmp(ptr,b); } - uint offset(byte *record) + uint offset(uchar *record) { - return (uint) (ptr - (char*) record); + return (uint) (ptr - record); } void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); @@ -411,7 +413,7 @@ public: /* maximum possible display length */ virtual uint32 max_display_length()= 0; - virtual uint is_equal(create_field *new_field); + virtual uint is_equal(Create_field *new_field); /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, int *err); @@ -421,10 +423,16 @@ public: return field_length / charset()->mbmaxlen; } + virtual geometry_type get_geometry_type() + { + /* shouldn't get here. */ + DBUG_ASSERT(0); + return GEOM_GEOMETRY; + } /* Hash value */ virtual void hash(ulong *nr, ulong *nr2); friend bool reopen_table(THD *,struct st_table *,bool); - friend int cre_myisam(my_string name, register TABLE *form, uint options, + friend int cre_myisam(char * name, register TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; friend class Item_avg_field; @@ -451,7 +459,7 @@ private: function. This represents the inheritance interface and can be overridden by subclasses. */ - virtual my_size_t do_last_null_byte() const; + virtual size_t do_last_null_byte() const; }; @@ -459,21 +467,21 @@ class Field_num :public Field { public: const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields - Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, + Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg); Item_result result_type () const { return REAL_RESULT; } void prepend_zeros(String *value); void add_zerofill_and_unsigned(String &res) const; - friend class create_field; + friend class Create_field; void make_field(Send_field *); uint decimals() const { return (uint) dec; } uint size_of() const { return sizeof(*this); } bool eq_def(Field *field); int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); - uint is_equal(create_field *new_field); + uint is_equal(Create_field *new_field); int check_int(CHARSET_INFO *cs, const char *str, int length, const char *int_end, int error); bool get_int(CHARSET_INFO *cs, const char *from, uint len, @@ -487,7 +495,7 @@ protected: CHARSET_INFO *field_charset; enum Derivation field_derivation; public: - Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, + Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *charset); Item_result result_type () const { return STRING_RESULT; } @@ -504,11 +512,11 @@ public: { field_derivation= derivation_arg; } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() { return field_length; } - friend class create_field; + friend class Create_field; my_decimal *val_decimal(my_decimal *); virtual bool str_needs_quotes() { return TRUE; } - bool compare_str_field_flags(create_field *new_field, uint32 flags); - uint is_equal(create_field *new_field); + bool compare_str_field_flags(Create_field *new_field, uint32 flags); + uint is_equal(Create_field *new_field); }; @@ -517,7 +525,7 @@ public: class Field_longstr :public Field_str { public: - Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *charset_arg) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, @@ -530,22 +538,27 @@ public: /* base class for float and double and decimal (old one) */ class Field_real :public Field_num { public: - Field_real(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + my_bool not_fixed; + + Field_real(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, dec_arg, zero_arg, unsigned_arg) + field_name_arg, dec_arg, zero_arg, unsigned_arg), + not_fixed(dec_arg >= NOT_FIXED_DEC) {} int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); + int truncate(double *nr, double max_length); uint32 max_display_length() { return field_length; } + uint size_of() const { return sizeof(*this); } }; class Field_decimal :public Field_real { public: - Field_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) @@ -563,8 +576,8 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; @@ -583,7 +596,7 @@ public: So for example we need to count length from precision handling CREATE TABLE ( DECIMAL(x,y)) */ - Field_new_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_new_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg); @@ -605,20 +618,20 @@ public: longlong val_int(void); my_decimal *val_decimal(my_decimal *); String *val_str(String*, String *); - int cmp(const char *, const char*); - void sort_string(char *buff, uint length); + int cmp(const uchar *, const uchar *); + void sort_string(uchar *buff, uint length); bool zero_pack() const { return 0; } void sql_type(String &str) const; uint32 max_display_length() { return field_length; } uint size_of() const { return sizeof(*this); } uint32 pack_length() const { return (uint32) bin_size; } - uint is_equal(create_field *new_field); + uint is_equal(Create_field *new_field); }; class Field_tiny :public Field_num { public: - Field_tiny(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, bool zero_arg, bool unsigned_arg) @@ -638,8 +651,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 1; } void sql_type(String &str) const; uint32 max_display_length() { return 4; } @@ -648,7 +661,7 @@ public: class Field_short :public Field_num { public: - Field_short(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_short(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, bool zero_arg, bool unsigned_arg) @@ -658,7 +671,7 @@ public: {} Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, bool unsigned_arg) - :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, 0, 0, unsigned_arg) {} enum Item_result result_type () const { return INT_RESULT; } @@ -673,8 +686,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 2; } void sql_type(String &str) const; uint32 max_display_length() { return 6; } @@ -683,7 +696,7 @@ public: class Field_medium :public Field_num { public: - Field_medium(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_medium(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, bool zero_arg, bool unsigned_arg) @@ -703,8 +716,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; uint32 max_display_length() { return 8; } @@ -713,7 +726,7 @@ public: class Field_long :public Field_num { public: - Field_long(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, bool zero_arg, bool unsigned_arg) @@ -723,7 +736,7 @@ public: {} Field_long(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, bool unsigned_arg) - :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg,0,0,unsigned_arg) {} enum Item_result result_type () const { return INT_RESULT; } @@ -738,18 +751,18 @@ public: longlong val_int(void); bool send_binary(Protocol *protocol); String *val_str(String*,String *); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; - uint32 max_display_length() { return 11; } + uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } }; #ifdef HAVE_LONG_LONG class Field_longlong :public Field_num { public: - Field_longlong(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_longlong(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, bool zero_arg, bool unsigned_arg) @@ -760,7 +773,7 @@ public: Field_longlong(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, bool unsigned_arg) - :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg,0,0,unsigned_arg) {} enum Item_result result_type () const { return INT_RESULT; } @@ -779,8 +792,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 8; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -791,7 +804,7 @@ public: class Field_float :public Field_real { public: - Field_float(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) @@ -801,7 +814,7 @@ public: {} Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg) - :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, NONE, field_name_arg, dec_arg, 0, 0) {} enum_field_types type() const { return MYSQL_TYPE_FLOAT;} @@ -814,8 +827,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; }; @@ -823,28 +836,24 @@ public: class Field_double :public Field_real { public: - my_bool not_fixed; - Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - dec_arg, zero_arg, unsigned_arg), - not_fixed(dec_arg >= NOT_FIXED_DEC) + dec_arg, zero_arg, unsigned_arg) {} Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg) - :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0), - not_fixed(dec_arg >= NOT_FIXED_DEC) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, dec_arg, 0, 0) {} Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, - uint8 dec_arg, my_bool not_fixed_srg) - :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0), - not_fixed(not_fixed_srg) - {} + uint8 dec_arg, my_bool not_fixed_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, dec_arg, 0, 0) + {not_fixed= not_fixed_arg; } enum_field_types type() const { return MYSQL_TYPE_DOUBLE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -855,11 +864,10 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; - uint size_of() const { return sizeof(*this); } }; @@ -868,7 +876,7 @@ public: class Field_null :public Field_str { static uchar null[1]; public: - Field_null(char *ptr_arg, uint32 len_arg, + Field_null(uchar *ptr_arg, uint32 len_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null, 1, @@ -886,8 +894,8 @@ public: my_decimal *val_decimal(my_decimal *) { return 0; } String *val_str(String *value,String *value2) { value2->length(0); return value2;} - int cmp(const char *a, const char *b) { return 0;} - void sort_string(char *buff, uint length) {} + int cmp(const uchar *a, const uchar *b) { return 0;} + void sort_string(uchar *buff, uint length) {} uint32 pack_length() const { return 0; } void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } @@ -897,7 +905,7 @@ public: class Field_timestamp :public Field_str { public: - Field_timestamp(char *ptr_arg, uint32 len_arg, + Field_timestamp(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, TABLE_SHARE *share, CHARSET_INFO *cs); @@ -914,8 +922,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -950,7 +958,7 @@ public: class Field_year :public Field_tiny { public: - Field_year(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_year(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg) :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, @@ -971,7 +979,7 @@ public: class Field_date :public Field_str { public: - Field_date(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, @@ -979,7 +987,7 @@ public: {} Field_date(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((char*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, + :Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_DATE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } @@ -992,8 +1000,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -1003,7 +1011,7 @@ public: class Field_newdate :public Field_str { public: - Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, @@ -1022,8 +1030,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -1035,7 +1043,7 @@ public: class Field_time :public Field_str { public: - Field_time(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + Field_time(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg, @@ -1043,7 +1051,7 @@ public: {} Field_time(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((char*) 0,8, maybe_null_arg ? (uchar*) "": 0,0, + :Field_str((uchar*) 0,8, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_TIME;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } @@ -1059,8 +1067,8 @@ public: bool get_date(MYSQL_TIME *ltime, uint fuzzydate); bool send_binary(Protocol *protocol); bool get_time(MYSQL_TIME *ltime); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -1070,7 +1078,7 @@ public: class Field_datetime :public Field_str { public: - Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + Field_datetime(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, @@ -1078,7 +1086,7 @@ public: {} Field_datetime(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((char*) 0,19, maybe_null_arg ? (uchar*) "": 0,0, + :Field_str((uchar*) 0,19, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_DATETIME;} #ifdef HAVE_LONG_LONG @@ -1099,8 +1107,8 @@ public: longlong val_int(void); String *val_str(String*,String *); bool send_binary(Protocol *protocol); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 8; } void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } @@ -1113,7 +1121,7 @@ public: class Field_string :public Field_longstr { public: bool can_alter_field_type; - Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, + Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) @@ -1122,7 +1130,7 @@ public: can_alter_field_type(1) {}; Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_longstr((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, + :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, cs), can_alter_field_type(1) {}; @@ -1139,7 +1147,7 @@ public: bool zero_pack() const { return 0; } int reset(void) { - charset()->cset->fill(charset(),ptr,field_length, + charset()->cset->fill(charset(),(char*) ptr, field_length, (has_charset() ? ' ' : 0)); return 0; } @@ -1150,30 +1158,35 @@ public: longlong val_int(void); String *val_str(String*,String *); my_decimal *val_decimal(my_decimal *); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); void sql_type(String &str) const; - char *pack(char *to, const char *from, uint max_length=~(uint) 0); - const char *unpack(char* to, const char *from); - int pack_cmp(const char *a,const char *b,uint key_length, + uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0); + const uchar *unpack(uchar* to, const uchar *from); + int pack_cmp(const uchar *a,const uchar *b,uint key_length, my_bool insert_or_update); - int pack_cmp(const char *b,uint key_length,my_bool insert_or_update); - uint packed_col_length(const char *to, uint length); + int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update); + uint packed_col_length(const uchar *to, uint length); uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return MYSQL_TYPE_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); - virtual uint get_key_image(char *buff,uint length, imagetype type); + virtual uint get_key_image(uchar *buff,uint length, imagetype type); }; class Field_varstring :public Field_longstr { public: + /* + The maximum space available in a Field_varstring, in bytes. See + length_bytes. + */ + static const uint MAX_SIZE= UINT_MAX16; /* Store number of bytes used to store length (1 or 2) */ uint32 length_bytes; - Field_varstring(char *ptr_arg, + Field_varstring(uchar *ptr_arg, uint32 len_arg, uint length_bytes_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, @@ -1187,7 +1200,7 @@ public: Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, TABLE_SHARE *share, CHARSET_INFO *cs) - :Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, + :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, cs), length_bytes(len_arg < 256 ? 1 :2) { @@ -1212,27 +1225,28 @@ public: longlong val_int(void); String *val_str(String*,String *); my_decimal *val_decimal(my_decimal *); - int cmp_max(const char *, const char *, uint max_length); - int cmp(const char *a,const char*b) + int cmp_max(const uchar *, const uchar *, uint max_length); + int cmp(const uchar *a,const uchar *b) { return cmp_max(a, b, ~0L); } - void sort_string(char *buff,uint length); - uint get_key_image(char *buff,uint length, imagetype type); - void set_key_image(char *buff,uint length); + void sort_string(uchar *buff,uint length); + uint get_key_image(uchar *buff,uint length, imagetype type); + void set_key_image(const uchar *buff,uint length); void sql_type(String &str) const; - char *pack(char *to, const char *from, uint max_length=~(uint) 0); - char *pack_key(char *to, const char *from, uint max_length); - char *pack_key_from_key_image(char* to, const char *from, uint max_length); - const char *unpack(char* to, const char *from); - const char *unpack_key(char* to, const char *from, uint max_length); - int pack_cmp(const char *a, const char *b, uint key_length, + uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0); + uchar *pack_key(uchar *to, const uchar *from, uint max_length); + uchar *pack_key_from_key_image(uchar* to, const uchar *from, + uint max_length); + const uchar *unpack(uchar* to, const uchar *from); + const uchar *unpack_key(uchar* to, const uchar *from, uint max_length); + int pack_cmp(const uchar *a, const uchar *b, uint key_length, my_bool insert_or_update); - int pack_cmp(const char *b, uint key_length,my_bool insert_or_update); - int cmp_binary(const char *a,const char *b, uint32 max_length=~0L); - int key_cmp(const byte *,const byte*); - int key_cmp(const byte *str, uint length); - uint packed_col_length(const char *to, uint length); + int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); + int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L); + int key_cmp(const uchar *,const uchar*); + int key_cmp(const uchar *str, uint length); + uint packed_col_length(const uchar *to, uint length); uint max_packed_col_length(uint max_length); uint32 data_length(); uint size_of() const { return sizeof(*this); } @@ -1241,9 +1255,9 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); - uint is_equal(create_field *new_field); + uint is_equal(Create_field *new_field); void hash(ulong *nr, ulong *nr2); }; @@ -1253,12 +1267,12 @@ protected: uint packlength; String value; // For temporaries public: - Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs); Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_longstr((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, + :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, cs), packlength(4) { @@ -1266,7 +1280,7 @@ public: } Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs, bool set_packlength) - :Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, + :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, cs) { flags|= BLOB_FLAG; @@ -1289,15 +1303,15 @@ public: longlong val_int(void); String *val_str(String*,String *); my_decimal *val_decimal(my_decimal *); - int cmp_max(const char *, const char *, uint max_length); - int cmp(const char *a,const char*b) + int cmp_max(const uchar *, const uchar *, uint max_length); + int cmp(const uchar *a,const uchar *b) { return cmp_max(a, b, ~0L); } - int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length); - int cmp_binary(const char *a,const char *b, uint32 max_length=~0L); - int key_cmp(const byte *,const byte*); - int key_cmp(const byte *str, uint length); + int cmp(const uchar *a, uint32 a_length, const uchar *b, uint32 b_length); + int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L); + int key_cmp(const uchar *,const uchar*); + int key_cmp(const uchar *str, uint length); uint32 key_length() const { return 0; } - void sort_string(char *buff,uint length); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->s->blob_ptr_size); } uint32 sort_length() const; @@ -1305,76 +1319,79 @@ public: { return (uint32) (((ulonglong) 1 << (packlength*8)) -1); } - int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; } - void reset_fields() { bzero((char*) &value,sizeof(value)); } + int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } + void reset_fields() { bzero((uchar*) &value,sizeof(value)); } #ifndef WORDS_BIGENDIAN static #endif - void store_length(char *i_ptr, uint i_packlength, uint32 i_number); + void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number); inline void store_length(uint32 number) { store_length(ptr, packlength, number); } - + inline uint32 get_length(uint row_offset=0) { return get_length(ptr+row_offset); } - uint32 get_length(const char *ptr); - void put_length(char *pos, uint32 length); - inline void get_ptr(char **str) + uint32 get_length(const uchar *ptr); + void put_length(uchar *pos, uint32 length); + inline void get_ptr(uchar **str) { - memcpy_fixed(str,ptr+packlength,sizeof(char*)); + memcpy_fixed((uchar*) str,ptr+packlength,sizeof(uchar*)); } - inline void get_ptr(char **str, uint row_offset) + inline void get_ptr(uchar **str, uint row_offset) { - memcpy_fixed(str,ptr+packlength+row_offset,sizeof(char*)); + memcpy_fixed((uchar*) str,ptr+packlength+row_offset,sizeof(char*)); } - inline void set_ptr(char *length,char *data) + inline void set_ptr(uchar *length, uchar *data) { memcpy(ptr,length,packlength); memcpy_fixed(ptr+packlength,&data,sizeof(char*)); } - void set_ptr_offset(my_ptrdiff_t ptr_diff, uint32 length,char *data) + void set_ptr_offset(my_ptrdiff_t ptr_diff, uint32 length, uchar *data) { - char *ptr_ofs= ADD_TO_PTR(ptr,ptr_diff,char*); + uchar *ptr_ofs= ADD_TO_PTR(ptr,ptr_diff,uchar*); store_length(ptr_ofs, packlength, length); memcpy_fixed(ptr_ofs+packlength,&data,sizeof(char*)); } - inline void set_ptr(uint32 length,char *data) + inline void set_ptr(uint32 length, uchar *data) { set_ptr_offset(0, length, data); } - uint get_key_image(char *buff,uint length, imagetype type); - void set_key_image(char *buff,uint length); + uint get_key_image(uchar *buff,uint length, imagetype type); + void set_key_image(const uchar *buff,uint length); void sql_type(String &str) const; inline bool copy() - { char *tmp; + { + uchar *tmp; get_ptr(&tmp); - if (value.copy(tmp,get_length(),charset())) + if (value.copy((char*) tmp, get_length(),charset())) { Field_blob::reset(); return 1; } - tmp=(char*) value.ptr(); memcpy_fixed(ptr+packlength,&tmp,sizeof(char*)); + tmp=(uchar*) value.ptr(); + memcpy_fixed(ptr+packlength,&tmp,sizeof(char*)); return 0; } - char *pack(char *to, const char *from, uint max_length= ~(uint) 0); - char *pack_key(char *to, const char *from, uint max_length); - char *pack_key_from_key_image(char* to, const char *from, uint max_length); - const char *unpack(char *to, const char *from); - const char *unpack_key(char* to, const char *from, uint max_length); - int pack_cmp(const char *a, const char *b, uint key_length, + uchar *pack(uchar *to, const uchar *from, uint max_length= ~(uint) 0); + uchar *pack_key(uchar *to, const uchar *from, uint max_length); + uchar *pack_key_from_key_image(uchar* to, const uchar *from, + uint max_length); + const uchar *unpack(uchar *to, const uchar *from); + const uchar *unpack_key(uchar* to, const uchar *from, uint max_length); + int pack_cmp(const uchar *a, const uchar *b, uint key_length, my_bool insert_or_update); - int pack_cmp(const char *b, uint key_length,my_bool insert_or_update); - uint packed_col_length(const char *col_ptr, uint length); + int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); + uint packed_col_length(const uchar *col_ptr, uint length); uint max_packed_col_length(uint max_length); void free() { value.free(); } - inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } + inline void clear_temporary() { bzero((uchar*) &value,sizeof(value)); } friend int field_conv(Field *to,Field *from); uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } uint32 max_display_length(); - uint is_equal(create_field *new_field); + uint is_equal(Create_field *new_field); }; @@ -1383,7 +1400,7 @@ class Field_geom :public Field_blob { public: enum geometry_type geom_type; - Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, + Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, enum geometry_type geom_type_arg) @@ -1401,9 +1418,10 @@ public: int store(double nr); int store(longlong nr, bool unsigned_val); int store_decimal(const my_decimal *); - uint get_key_image(char *buff,uint length,imagetype type); + uint get_key_image(uchar *buff,uint length,imagetype type); uint size_of() const { return sizeof(*this); } int reset(void) { return !maybe_null() || Field_blob::reset(); } + geometry_type get_geometry_type() { return geom_type; }; }; #endif /*HAVE_SPATIAL*/ @@ -1413,7 +1431,7 @@ protected: uint packlength; public: TYPELIB *typelib; - Field_enum(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint packlength_arg, @@ -1436,8 +1454,8 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - int cmp(const char *,const char*); - void sort_string(char *buff,uint length); + int cmp(const uchar *,const uchar *); + void sort_string(uchar *buff,uint length); uint32 pack_length() const { return (uint32) packlength; } void store_type(ulonglong value); void sql_type(String &str) const; @@ -1454,7 +1472,7 @@ public: class Field_set :public Field_enum { public: - Field_set(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_set(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, uint32 packlength_arg, @@ -1497,7 +1515,7 @@ public: uchar bit_ofs; // offset to 'uneven' high bits uint bit_len; // number of 'uneven' high bits uint bytes_in_rec; - Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, enum utype unireg_check_arg, const char *field_name_arg); enum_field_types type() const { return MYSQL_TYPE_BIT; } @@ -1516,29 +1534,29 @@ public: String *val_str(String*, String *); virtual bool str_needs_quotes() { return TRUE; } my_decimal *val_decimal(my_decimal *); - int cmp(const char *a, const char *b) + int cmp(const uchar *a, const uchar *b) { return cmp_binary(a, b); } int cmp_binary_offset(uint row_offset) { return cmp_offset(row_offset); } - int cmp_max(const char *a, const char *b, uint max_length); - int key_cmp(const byte *a, const byte *b) - { return cmp_binary((char *) a, (char *) b); } - int key_cmp(const byte *str, uint length); + int cmp_max(const uchar *a, const uchar *b, uint max_length); + int key_cmp(const uchar *a, const uchar *b) + { return cmp_binary((uchar *) a, (uchar *) b); } + int key_cmp(const uchar *str, uint length); int cmp_offset(uint row_offset); - uint get_key_image(char *buff, uint length, imagetype type); - void set_key_image(char *buff, uint length) - { Field_bit::store(buff, length, &my_charset_bin); } - void sort_string(char *buff, uint length) + uint get_key_image(uchar *buff, uint length, imagetype type); + void set_key_image(const uchar *buff, uint length) + { Field_bit::store((char*) buff, length, &my_charset_bin); } + void sort_string(uchar *buff, uint length) { get_key_image(buff, length, itRAW); } uint32 pack_length() const { return (uint32) (field_length + 7) / 8; } uint32 pack_length_in_rec() const { return bytes_in_rec; } void sql_type(String &str) const; - char *pack(char *to, const char *from, uint max_length=~(uint) 0); - const char *unpack(char* to, const char *from); + uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0); + const uchar *unpack(uchar* to, const uchar *from); virtual void set_default(); Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, + uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg) { @@ -1552,6 +1570,7 @@ public: bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ofs == ((Field_bit *)field)->bit_ofs); } + uint is_equal(Create_field *new_field); void move_field_offset(my_ptrdiff_t ptr_diff) { Field::move_field_offset(ptr_diff); @@ -1559,7 +1578,7 @@ public: } private: - virtual my_size_t do_last_null_byte() const; + virtual size_t do_last_null_byte() const; }; @@ -1572,7 +1591,7 @@ private: */ class Field_bit_as_char: public Field_bit { public: - Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + Field_bit_as_char(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg); enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } @@ -1589,7 +1608,7 @@ public: Create field class for CREATE TABLE */ -class create_field :public Sql_alloc +class Create_field :public Sql_alloc { public: const char *field_name; @@ -1620,8 +1639,11 @@ public: uint8 row,col,sc_length,interval_id; // For rea_create_table uint offset,pack_flag; - create_field() :after(0) {} - create_field(Field *field, Field *orig_field); + Create_field() :after(0) {} + Create_field(Field *field, Field *orig_field); + /* Used to make a clone of this object for ALTER/CREATE TABLE */ + Create_field *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Create_field(*this); } void create_length_to_internal_length(void); /* Init for a tmp table field. To be extended if need be. */ @@ -1660,7 +1682,7 @@ class Send_field { class Copy_field :public Sql_alloc { void (*get_copy_func(Field *to,Field *from))(Copy_field *); public: - char *from_ptr,*to_ptr; + uchar *from_ptr,*to_ptr; uchar *from_null_ptr,*to_null_ptr; my_bool *null_row; uint from_bit,to_bit; @@ -1671,13 +1693,13 @@ public: Copy_field() {} ~Copy_field() {} void set(Field *to,Field *from,bool save); // Field to field - void set(char *to,Field *from); // Field to string + void set(uchar *to,Field *from); // Field to string void (*do_copy)(Copy_field *); void (*do_copy2)(Copy_field *); // Used to handle null values }; -Field *make_field(TABLE_SHARE *share, char *ptr, uint32 field_length, +Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length, uchar *null_pos, uchar null_bit, uint pack_flag, enum_field_types field_type, CHARSET_INFO *cs, diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 9771cbc12b1..63810c8b113 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -355,8 +355,8 @@ static void do_cut_string(Copy_field *copy) /* Check if we loosed any important characters */ if (cs->cset->scan(cs, - copy->from_ptr + copy->to_length, - copy->from_ptr + copy->from_length, + (char*) copy->from_ptr + copy->to_length, + (char*) copy->from_ptr + copy->from_length, MY_SEQ_SPACES) < copy->from_length - copy->to_length) { copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, @@ -374,8 +374,10 @@ static void do_cut_string_complex(Copy_field *copy) { // Shorter string field int well_formed_error; CHARSET_INFO *cs= copy->from_field->charset(); - const char *from_end= copy->from_ptr + copy->from_length; - uint copy_length= cs->cset->well_formed_len(cs, copy->from_ptr, from_end, + const uchar *from_end= copy->from_ptr + copy->from_length; + uint copy_length= cs->cset->well_formed_len(cs, + (char*) copy->from_ptr, + (char*) from_end, copy->to_length / cs->mbmaxlen, &well_formed_error); if (copy->to_length < copy_length) @@ -384,7 +386,8 @@ static void do_cut_string_complex(Copy_field *copy) /* Check if we lost any important characters */ if (well_formed_error || - cs->cset->scan(cs, copy->from_ptr + copy_length, from_end, + cs->cset->scan(cs, (char*) copy->from_ptr + copy_length, + (char*) from_end, MY_SEQ_SPACES) < (copy->from_length - copy_length)) { copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, @@ -392,7 +395,7 @@ static void do_cut_string_complex(Copy_field *copy) } if (copy_length < copy->to_length) - cs->cset->fill(cs, copy->to_ptr + copy_length, + cs->cset->fill(cs, (char*) copy->to_ptr + copy_length, copy->to_length - copy_length, ' '); } @@ -403,7 +406,7 @@ static void do_expand_binary(Copy_field *copy) { CHARSET_INFO *cs= copy->from_field->charset(); memcpy(copy->to_ptr,copy->from_ptr,copy->from_length); - cs->cset->fill(cs, copy->to_ptr+copy->from_length, + cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length, copy->to_length-copy->from_length, '\0'); } @@ -413,7 +416,7 @@ static void do_expand_string(Copy_field *copy) { CHARSET_INFO *cs= copy->from_field->charset(); memcpy(copy->to_ptr,copy->from_ptr,copy->from_length); - cs->cset->fill(cs, copy->to_ptr+copy->from_length, + cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length, copy->to_length-copy->from_length, ' '); } @@ -438,9 +441,10 @@ static void do_varstring1_mb(Copy_field *copy) int well_formed_error; CHARSET_INFO *cs= copy->from_field->charset(); uint from_length= (uint) *(uchar*) copy->from_ptr; - const char *from_ptr= copy->from_ptr + 1; + const uchar *from_ptr= copy->from_ptr + 1; uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen; - uint length= cs->cset->well_formed_len(cs, from_ptr, from_ptr + from_length, + uint length= cs->cset->well_formed_len(cs, (char*) from_ptr, + (char*) from_ptr + from_length, to_char_length, &well_formed_error); if (length < from_length) { @@ -448,7 +452,7 @@ static void do_varstring1_mb(Copy_field *copy) copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } - *(uchar*) copy->to_ptr= (uchar) length; + *copy->to_ptr= (uchar) length; memcpy(copy->to_ptr + 1, from_ptr, length); } @@ -475,8 +479,9 @@ static void do_varstring2_mb(Copy_field *copy) CHARSET_INFO *cs= copy->from_field->charset(); uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen; uint from_length= uint2korr(copy->from_ptr); - const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; - uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length, + const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; + uint length= cs->cset->well_formed_len(cs, (char*) from_beg, + (char*) from_beg + from_length, char_length, &well_formed_error); if (length < from_length) { @@ -501,7 +506,7 @@ static void do_varstring2_mb(Copy_field *copy) The 'to' buffer should have a size of field->pack_length()+1 */ -void Copy_field::set(char *to,Field *from) +void Copy_field::set(uchar *to,Field *from) { from_ptr=from->ptr; to_ptr=to; @@ -529,7 +534,21 @@ void Copy_field::set(char *to,Field *from) } +/* + To do: + + If 'save\ is set to true and the 'from' is a blob field, do_copy is set to + do_save_blob rather than do_conv_blob. The only differences between them + appears to be: + - do_save_blob allocates and uses an intermediate buffer before calling + Field_blob::store. Is this in order to trigger the call to + well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()? + That call will take place anyway in all known cases. + + - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended + effect? Truncation is handled by well_formed_copy_nchars anyway. + */ void Copy_field::set(Field *to,Field *from,bool save) { if (to->type() == MYSQL_TYPE_NULL) diff --git a/sql/filesort.cc b/sql/filesort.cc index 01ba3f06fc7..b1dfb4d5e71 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -30,19 +30,20 @@ /* How to write record_ref. */ #define WRITE_REF(file,from) \ -if (my_b_write((file),(byte*) (from),param->ref_length)) \ +if (my_b_write((file),(uchar*) (from),param->ref_length)) \ DBUG_RETURN(1); /* functions defined in this file */ -static char **make_char_array(register uint fields, uint length, myf my_flag); +static char **make_char_array(char **old_pos, register uint fields, + uint length, myf my_flag); static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffer_file, uint count); static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select, uchar * *sort_keys, IO_CACHE *buffer_file, IO_CACHE *tempfile,IO_CACHE *indexfile); static int write_keys(SORTPARAM *param,uchar * *sort_keys, uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile); -static void make_sortkey(SORTPARAM *param,uchar *to, byte *ref_pos); +static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos); static void register_used_fields(SORTPARAM *param); static int merge_index(SORTPARAM *param,uchar *sort_buffer, BUFFPEK *buffpek, @@ -56,7 +57,7 @@ static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, - byte *buff); + uchar *buff); /* Sort a table @@ -153,7 +154,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (param.addon_field) { param.res_length= param.addon_length; - if (!(table_sort.addon_buf= (byte *) my_malloc(param.addon_length, + if (!(table_sort.addon_buf= (uchar *) my_malloc(param.addon_length, MYF(MY_WME)))) goto err; } @@ -171,11 +172,11 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (select && select->quick) { - statistic_increment(thd->status_var.filesort_range_count, &LOCK_status); + status_var_increment(thd->status_var.filesort_range_count); } else { - statistic_increment(thd->status_var.filesort_scan_count, &LOCK_status); + status_var_increment(thd->status_var.filesort_scan_count); } #ifdef CAN_TRUST_RANGE if (select && select->quick && select->quick->records > 0L) @@ -198,7 +199,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } if (multi_byte_charset && - !(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME)))) + !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME)))) goto err; memavl= thd->variables.sortbuff_size; @@ -208,9 +209,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ulong old_memavl; ulong keys= memavl/(param.rec_length+sizeof(char*)); param.keys=(uint) min(records+1, keys); - if (table_sort.sort_keys || - (table_sort.sort_keys= (uchar **) make_char_array(param.keys, param.rec_length, - MYF(0)))) + if ((table_sort.sort_keys= + (uchar **) make_char_array((char **) table_sort.sort_keys, + param.keys, param.rec_length, MYF(0)))) break; old_memavl=memavl; if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory) @@ -245,7 +246,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, { if (!table_sort.buffpek && table_sort.buffpek_len < maxbuffer && !(table_sort.buffpek= - (byte *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) + (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) goto err; buffpek= (BUFFPEK *) table_sort.buffpek; table_sort.buffpek_len= maxbuffer; @@ -284,9 +285,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, x_free(param.tmp_buffer); if (!subselect || !subselect->is_uncacheable()) { - x_free((gptr) sort_keys); + x_free((uchar*) sort_keys); table_sort.sort_keys= 0; - x_free((gptr) buffpek); + x_free((uchar*) buffpek); table_sort.buffpek= 0; table_sort.buffpek_len= 0; } @@ -324,19 +325,19 @@ void filesort_free_buffers(TABLE *table, bool full) { if (table->sort.record_pointers) { - my_free((gptr) table->sort.record_pointers,MYF(0)); + my_free((uchar*) table->sort.record_pointers,MYF(0)); table->sort.record_pointers=0; } if (full) { if (table->sort.sort_keys ) { - x_free((gptr) table->sort.sort_keys); + x_free((uchar*) table->sort.sort_keys); table->sort.sort_keys= 0; } if (table->sort.buffpek) { - x_free((gptr) table->sort.buffpek); + x_free((uchar*) table->sort.buffpek); table->sort.buffpek= 0; table->sort.buffpek_len= 0; } @@ -352,14 +353,16 @@ void filesort_free_buffers(TABLE *table, bool full) /* Make a array of string pointers */ -static char **make_char_array(register uint fields, uint length, myf my_flag) +static char **make_char_array(char **old_pos, register uint fields, + uint length, myf my_flag) { register char **pos; - char **old_pos,*char_pos; + char *char_pos; DBUG_ENTER("make_char_array"); - if ((old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)), - my_flag))) + if (old_pos || + (old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)), + my_flag))) { pos=old_pos; char_pos=((char*) (pos+fields)) -length; while (fields--) *(pos++) = (char_pos+= length); @@ -382,7 +385,7 @@ static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count) if (tmp) { if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || - my_b_read(buffpek_pointers, (byte*) tmp, length)) + my_b_read(buffpek_pointers, (uchar*) tmp, length)) { my_free((char*) tmp, MYF(0)); tmp=0; @@ -434,7 +437,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { int error,flag,quick_select; uint idx,indexpos,ref_length; - byte *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; + uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; my_off_t record; TABLE *sort_form; THD *thd= current_thd; @@ -461,7 +464,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, next_pos=ref_pos; if (! indexfile && ! quick_select) { - next_pos=(byte*) 0; /* Find records in sequence */ + next_pos=(uchar*) 0; /* Find records in sequence */ file->ha_rnd_init(1); file->extra_opt(HA_EXTRA_CACHE, current_thd->variables.read_buff_size); @@ -486,7 +489,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, register_used_fields(param); if (select && select->cond) select->cond->walk(&Item::register_field_in_read_map, 1, - (byte*) sort_form); + (uchar*) sort_form); sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set); for (;;) @@ -504,7 +507,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { if (indexfile) { - if (my_b_read(indexfile,(byte*) ref_pos,ref_length)) /* purecov: deadcode */ + if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */ { error= my_errno ? my_errno : -1; /* Abort */ break; @@ -612,7 +615,7 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, IO_CACHE *buffpek_pointers, IO_CACHE *tempfile) { - uint sort_length, rec_length; + size_t sort_length, rec_length; uchar **end; BUFFPEK buffpek; DBUG_ENTER("write_keys"); @@ -622,7 +625,7 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, #ifdef MC68000 quicksort(sort_keys,count,sort_length); #else - my_string_ptr_sort((gptr) sort_keys, (uint) count, sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length); #endif if (!my_b_inited(tempfile) && open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE, @@ -636,9 +639,9 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, count=(uint) param->max_rows; /* purecov: inspected */ buffpek.count=(ha_rows) count; for (end=sort_keys+count ; sort_keys != end ; sort_keys++) - if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length)) + if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length)) goto err; - if (my_b_write(buffpek_pointers, (byte*) &buffpek, sizeof(buffpek))) + if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek))) goto err; DBUG_RETURN(0); @@ -673,7 +676,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length) /* makes a sort-key from record */ static void make_sortkey(register SORTPARAM *param, - register uchar *to, byte *ref_pos) + register uchar *to, uchar *ref_pos) { reg3 Field *field; reg1 SORT_FIELD *sort_field; @@ -700,7 +703,7 @@ static void make_sortkey(register SORTPARAM *param, else *to++=1; } - field->sort_string((char*) to,sort_field->length); + field->sort_string(to, sort_field->length); } else { // Item @@ -829,7 +832,7 @@ static void make_sortkey(register SORTPARAM *param, } *to++=1; } - my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, (char*)to, + my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to, item->max_length - (item->decimals ? 1:0), item->decimals); break; @@ -847,7 +850,7 @@ static void make_sortkey(register SORTPARAM *param, } *to++=1; } - change_double_for_sort(value,(byte*) to); + change_double_for_sort(value,(uchar*) to); break; } case ROW_RESULT: @@ -897,13 +900,13 @@ static void make_sortkey(register SORTPARAM *param, else { #ifdef HAVE_purify - uchar *end= (uchar*) field->pack((char *) to, field->ptr); + uchar *end= field->pack(to, field->ptr); uint length= (uint) ((to + addonf->length) - end); DBUG_ASSERT((int) length >= 0); if (length) bzero(end, length); #else - (void) field->pack((char *) to, field->ptr); + (void) field->pack(to, field->ptr); #endif } to+= addonf->length; @@ -912,7 +915,7 @@ static void make_sortkey(register SORTPARAM *param, else { /* Save filepos last */ - memcpy((byte*) to, ref_pos, (size_s) param->ref_length); + memcpy((uchar*) to, ref_pos, (size_t) param->ref_length); } return; } @@ -941,7 +944,7 @@ static void register_used_fields(SORTPARAM *param) else { // Item sort_field->item->walk(&Item::register_field_in_read_map, 1, - (byte *) table); + (uchar *) table); } } @@ -964,16 +967,16 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, FILESORT_INFO *table_sort) { uint offset,res_length; - byte *to; + uchar *to; DBUG_ENTER("save_index"); - my_string_ptr_sort((gptr) sort_keys, (uint) count, param->sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length); res_length= param->res_length; offset= param->rec_length-res_length; if ((ha_rows) count > param->max_rows) count=(uint) param->max_rows; if (!(to= table_sort->record_pointers= - (byte*) my_malloc(res_length*count, MYF(MY_WME)))) + (uchar*) my_malloc(res_length*count, MYF(MY_WME)))) DBUG_RETURN(1); /* purecov: inspected */ for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++) { @@ -1048,7 +1051,7 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) { - if (my_pread(fromfile->file,(byte*) buffpek->base, + if (my_pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos,MYF_RW)) return((uint) -1); /* purecov: inspected */ buffpek->key=buffpek->base; @@ -1129,8 +1132,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, THD::killed_state not_killable; DBUG_ENTER("merge_buffers"); - statistic_increment(current_thd->status_var.filesort_merge_passes, - &LOCK_status); + status_var_increment(current_thd->status_var.filesort_merge_passes); if (param->not_killable) { killed= ¬_killable; @@ -1163,7 +1165,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, if (error == -1) goto err; /* purecov: inspected */ buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected - queue_insert(&queue, (byte*) buffpek); + queue_insert(&queue, (uchar*) buffpek); } if (param->unique_buff) @@ -1178,7 +1180,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, */ buffpek= (BUFFPEK*) queue_top(&queue); memcpy(param->unique_buff, buffpek->key, rec_length); - if (my_b_write(to_file, (byte*) buffpek->key, rec_length)) + if (my_b_write(to_file, (uchar*) buffpek->key, rec_length)) { error=1; goto err; /* purecov: inspected */ } @@ -1212,14 +1214,14 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, } if (flag == 0) { - if (my_b_write(to_file,(byte*) buffpek->key, rec_length)) + if (my_b_write(to_file,(uchar*) buffpek->key, rec_length)) { error=1; goto err; /* purecov: inspected */ } } else { - if (my_b_write(to_file, (byte*) buffpek->key+offset, res_length)) + if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length)) { error=1; goto err; /* purecov: inspected */ } @@ -1274,7 +1276,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, max_rows-= buffpek->mem_count; if (flag == 0) { - if (my_b_write(to_file,(byte*) buffpek->key, + if (my_b_write(to_file,(uchar*) buffpek->key, (rec_length*buffpek->mem_count))) { error= 1; goto err; /* purecov: inspected */ @@ -1288,7 +1290,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, strpos != end ; strpos+= rec_length) { - if (my_b_write(to_file, (byte *) strpos, res_length)) + if (my_b_write(to_file, (uchar *) strpos, res_length)) { error=1; goto err; } @@ -1557,7 +1559,7 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) */ static void -unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) +unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff) { Field *field; SORT_ADDON_FIELD *addonf= addon_field; @@ -1570,7 +1572,7 @@ unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) continue; } field->set_notnull(); - field->unpack(field->ptr, (char *) buff+addonf->offset); + field->unpack(field->ptr, buff + addonf->offset); } } @@ -1581,7 +1583,7 @@ unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) #define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG) -void change_double_for_sort(double nr,byte *to) +void change_double_for_sort(double nr,uchar *to) { uchar *tmp=(uchar*) to; if (nr == 0.0) diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 2d78999017a..36b7f30dc64 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -90,8 +90,8 @@ struct my_option my_long_options[] = {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log", (gptr*) &default_dbug_option, - (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", (uchar**) &default_dbug_option, + (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"help", '?', "Display help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/sql/gstream.h b/sql/gstream.h index 10274635413..1ef90ad5bf0 100644 --- a/sql/gstream.h +++ b/sql/gstream.h @@ -35,7 +35,7 @@ public: {} ~Gis_read_stream() { - my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*) m_err_msg, MYF(MY_ALLOW_ZERO_PTR)); } enum enum_tok_types get_next_toc_type(); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index bb5b84da525..c78cb4e65b4 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -146,7 +146,7 @@ pthread_mutex_t ndbcluster_mutex; // Table lock handling HASH ndbcluster_open_tables; -static byte *ndbcluster_get_key(NDB_SHARE *share,uint *length, +static uchar *ndbcluster_get_key(NDB_SHARE *share, size_t *length, my_bool not_used __attribute__((unused))); #ifdef HAVE_NDB_BINLOG static int rename_share(NDB_SHARE *share, const char *new_key); @@ -316,11 +316,11 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans, Place holder for ha_ndbcluster thread specific data */ static -byte *thd_ndb_share_get_key(THD_NDB_SHARE *thd_ndb_share, uint *length, +uchar *thd_ndb_share_get_key(THD_NDB_SHARE *thd_ndb_share, size_t *length, my_bool not_used __attribute__((unused))) { *length= sizeof(thd_ndb_share->key); - return (byte*) &thd_ndb_share->key; + return (uchar*) &thd_ndb_share->key; } Thd_ndb::Thd_ndb() @@ -375,9 +375,9 @@ Thd_ndb::get_open_table(THD *thd, const void *key) DBUG_ENTER("Thd_ndb::get_open_table"); HASH_SEARCH_STATE state; THD_NDB_SHARE *thd_ndb_share= - (THD_NDB_SHARE*)hash_first(&open_tables, (byte *)&key, sizeof(key), &state); + (THD_NDB_SHARE*)hash_first(&open_tables, (uchar *)&key, sizeof(key), &state); while (thd_ndb_share && thd_ndb_share->key != key) - thd_ndb_share= (THD_NDB_SHARE*)hash_next(&open_tables, (byte *)&key, sizeof(key), &state); + thd_ndb_share= (THD_NDB_SHARE*)hash_next(&open_tables, (uchar *)&key, sizeof(key), &state); if (thd_ndb_share == 0) { thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root, @@ -386,7 +386,7 @@ Thd_ndb::get_open_table(THD *thd, const void *key) thd_ndb_share->stat.last_count= count; thd_ndb_share->stat.no_uncommitted_rows_count= 0; thd_ndb_share->stat.records= ~(ha_rows)0; - my_hash_insert(&open_tables, (byte *)thd_ndb_share); + my_hash_insert(&open_tables, (uchar *)thd_ndb_share); } else if (thd_ndb_share->stat.last_count != count) { @@ -692,7 +692,7 @@ static bool field_type_forces_var_part(enum_field_types type) */ bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op, - uint fieldnr, const byte *field_ptr) + uint fieldnr, const uchar *field_ptr) { DBUG_ENTER("set_hidden_key"); DBUG_RETURN(ndb_op->equal(fieldnr, (char*)field_ptr) != 0); @@ -704,14 +704,14 @@ bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op, */ int ha_ndbcluster::set_ndb_key(NdbOperation *ndb_op, Field *field, - uint fieldnr, const byte *field_ptr) + uint fieldnr, const uchar *field_ptr) { uint32 pack_len= field->pack_length(); DBUG_ENTER("set_ndb_key"); DBUG_PRINT("enter", ("%d: %s, ndb_type: %u, len=%d", fieldnr, field->field_name, field->type(), pack_len)); - DBUG_DUMP("key", (char*)field_ptr, pack_len); + DBUG_DUMP("key", field_ptr, pack_len); DBUG_ASSERT(ndb_supported_type(field->type())); DBUG_ASSERT(! (field->flags & BLOB_FLAG)); @@ -728,13 +728,13 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, uint fieldnr, int row_offset, bool *set_blob_value) { - const byte* field_ptr= field->ptr + row_offset; + const uchar* field_ptr= field->ptr + row_offset; uint32 pack_len= field->pack_length(); DBUG_ENTER("set_ndb_value"); DBUG_PRINT("enter", ("%d: %s type: %u len=%d is_null=%s", fieldnr, field->field_name, field->type(), pack_len, field->is_null(row_offset) ? "Y" : "N")); - DBUG_DUMP("value", (char*) field_ptr, pack_len); + DBUG_DUMP("value", field_ptr, pack_len); DBUG_ASSERT(ndb_supported_type(field->type())); { @@ -743,7 +743,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, if (pack_len == 0) { pack_len= sizeof(empty_field); - field_ptr= (byte *)&empty_field; + field_ptr= (uchar *)&empty_field; if (field->is_null(row_offset)) empty_field= 0; else @@ -773,7 +773,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, // Set value to NULL DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL) != 0)); DBUG_PRINT("info", ("bit field")); - DBUG_DUMP("value", (char*)&bits, pack_len); + DBUG_DUMP("value", (uchar*)&bits, pack_len); #ifdef WORDS_BIGENDIAN /* store lsw first */ bits = ((bits >> 32) & 0x00000000FFFFFFFFLL) @@ -793,18 +793,18 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, // Get length and pointer to data uint32 blob_len= field_blob->get_length(field_ptr); - char* blob_ptr= NULL; + uchar* blob_ptr= NULL; field_blob->get_ptr(&blob_ptr); // Looks like NULL ptr signals length 0 blob if (blob_ptr == NULL) { DBUG_ASSERT(blob_len == 0); - blob_ptr= (char*)""; + blob_ptr= (uchar*)""; } DBUG_PRINT("value", ("set blob ptr: 0x%lx len: %u", (long) blob_ptr, blob_len)); - DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26)); + DBUG_DUMP("value", blob_ptr, min(blob_len, 26)); if (set_blob_value) *set_blob_value= TRUE; @@ -848,7 +848,7 @@ int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg) passes a record pointer diff. */ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, - byte*& buffer, uint& buffer_size, + uchar*& buffer, uint& buffer_size, my_ptrdiff_t ptrdiff) { DBUG_ENTER("get_ndb_blobs_value"); @@ -884,7 +884,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, size+= 8 - size % 8; if (loop == 1) { - char *buf= buffer + offset; + uchar *buf= buffer + offset; uint32 len= 0xffffffff; // Max uint32 if (ndb_blob->readData(buf, len) != 0) ERR_RETURN(ndb_blob->getNdbError()); @@ -899,9 +899,9 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, else if (loop == 1) // undefined or null { // have to set length even in this case - char *buf= buffer + offset; // or maybe NULL + uchar *buf= buffer + offset; // or maybe NULL uint32 len= 0; - field_blob->set_ptr_offset(ptrdiff, len, buf); + field_blob->set_ptr_offset(ptrdiff, len, buf); DBUG_PRINT("info", ("[%u] isNull=%d", i, isNull)); } } @@ -910,7 +910,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, my_free(buffer, MYF(MY_ALLOW_ZERO_PTR)); buffer_size= 0; DBUG_PRINT("info", ("allocate blobs buffer size %u", offset)); - buffer= my_malloc(offset, MYF(MY_WME)); + buffer= (uchar*) my_malloc(offset, MYF(MY_WME)); if (buffer == NULL) { sql_print_error("ha_ndbcluster::get_ndb_blobs_value: " @@ -931,7 +931,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, */ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, - uint fieldnr, byte* buf) + uint fieldnr, uchar* buf) { DBUG_ENTER("get_ndb_value"); DBUG_PRINT("enter", ("fieldnr: %d flags: %o", fieldnr, @@ -946,13 +946,13 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, { if (field->type() != MYSQL_TYPE_BIT) { - byte *field_buf; + uchar *field_buf; if (field->pack_length() != 0) field_buf= buf + (field->ptr - table->record[0]); else - field_buf= (byte *)&dummy_buf; + field_buf= (uchar *)&dummy_buf; m_value[fieldnr].rec= ndb_op->getValue(fieldnr, - field_buf); + (char*) field_buf); } else // if (field->type() == MYSQL_TYPE_BIT) { @@ -967,7 +967,7 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, if (ndb_blob != NULL) { // Set callback - m_blobs_offset= buf - (byte*) table->record[0]; + m_blobs_offset= buf - (uchar*) table->record[0]; void *arg= (void *)this; DBUG_RETURN(ndb_blob->setActiveHook(g_get_ndb_blobs_value, arg) != 0); } @@ -975,7 +975,7 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, } // Used for hidden key only - m_value[fieldnr].rec= ndb_op->getValue(fieldnr, m_ref); + m_value[fieldnr].rec= ndb_op->getValue(fieldnr, (char*) m_ref); DBUG_RETURN(m_value[fieldnr].rec == NULL); } @@ -1049,8 +1049,8 @@ int ha_ndbcluster::get_metadata(const char *path) DBUG_ASSERT(m_table == NULL); DBUG_ASSERT(m_table_info == NULL); - const void *data= NULL, *pack_data= NULL; - uint length, pack_length; + uchar *data= NULL, *pack_data= NULL; + size_t length, pack_length; /* Compare FrmData in NDB with frm file from disk. @@ -1059,8 +1059,8 @@ int ha_ndbcluster::get_metadata(const char *path) if (readfrm(path, &data, &length) || packfrm(data, length, &pack_data, &pack_length)) { - my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR)); + my_free(data, MYF(MY_ALLOW_ZERO_PTR)); + my_free(pack_data, MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(1); } @@ -1072,11 +1072,11 @@ int ha_ndbcluster::get_metadata(const char *path) && cmp_frm(tab, pack_data, pack_length)) { DBUG_PRINT("error", - ("metadata, pack_length: %d getFrmLength: %d memcmp: %d", - pack_length, tab->getFrmLength(), + ("metadata, pack_length: %lu getFrmLength: %d memcmp: %d", + (ulong) pack_length, tab->getFrmLength(), memcmp(pack_data, tab->getFrmData(), pack_length))); - DBUG_DUMP("pack_data", (char*)pack_data, pack_length); - DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength()); + DBUG_DUMP("pack_data", (uchar*) pack_data, pack_length); + DBUG_DUMP("frm", (uchar*) tab->getFrmData(), tab->getFrmLength()); error= HA_ERR_TABLE_DEF_CHANGED; } my_free((char*)data, MYF(0)); @@ -1579,7 +1579,7 @@ inline ulong ha_ndbcluster::index_flags(uint idx_no, uint part, HA_KEY_SCAN_NOT_ROR); } -static void shrink_varchar(Field* field, const byte* & ptr, char* buf) +static void shrink_varchar(Field* field, const uchar* & ptr, uchar* buf) { if (field->type() == MYSQL_TYPE_VARCHAR && ptr != NULL) { Field_varstring* f= (Field_varstring*)field; @@ -1598,7 +1598,7 @@ static void shrink_varchar(Field* field, const byte* & ptr, char* buf) } } -int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key) +int ha_ndbcluster::set_primary_key(NdbOperation *op, const uchar *key) { KEY* key_info= table->key_info + table_share->primary_key; KEY_PART_INFO* key_part= key_info->key_part; @@ -1608,8 +1608,8 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key) for (; key_part != end; key_part++) { Field* field= key_part->field; - const byte* ptr= key; - char buf[256]; + const uchar* ptr= key; + uchar buf[256]; shrink_varchar(field, ptr, buf); if (set_ndb_key(op, field, key_part->fieldnr-1, ptr)) @@ -1620,7 +1620,7 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key) } -int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *record) +int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const uchar *record) { KEY* key_info= table->key_info + table_share->primary_key; KEY_PART_INFO* key_part= key_info->key_part; @@ -1638,7 +1638,7 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *rec } int ha_ndbcluster::set_index_key_from_record(NdbOperation *op, - const byte *record, uint keyno) + const uchar *record, uint keyno) { KEY* key_info= table->key_info + keyno; KEY_PART_INFO* key_part= key_info->key_part; @@ -1659,7 +1659,7 @@ int ha_ndbcluster::set_index_key_from_record(NdbOperation *op, int ha_ndbcluster::set_index_key(NdbOperation *op, const KEY *key_info, - const byte * key_ptr) + const uchar * key_ptr) { DBUG_ENTER("ha_ndbcluster::set_index_key"); uint i; @@ -1669,8 +1669,8 @@ ha_ndbcluster::set_index_key(NdbOperation *op, for (i= 0; key_part != end; key_part++, i++) { Field* field= key_part->field; - const byte* ptr= key_part->null_bit ? key_ptr + 1 : key_ptr; - char buf[256]; + const uchar* ptr= key_part->null_bit ? key_ptr + 1 : key_ptr; + uchar buf[256]; shrink_varchar(field, ptr, buf); if (set_ndb_key(op, field, m_index[active_index].unique_index_attrid_map[i], ptr)) ERR_RETURN(m_active_trans->getNdbError()); @@ -1680,7 +1680,7 @@ ha_ndbcluster::set_index_key(NdbOperation *op, } inline -int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op) +int ha_ndbcluster::define_read_attrs(uchar* buf, NdbOperation* op) { uint i; DBUG_ENTER("define_read_attrs"); @@ -1722,7 +1722,7 @@ int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op) Read one record from NDB using primary key */ -int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf, +int ha_ndbcluster::pk_read(const uchar *key, uint key_len, uchar *buf, uint32 part_id) { uint no_fields= table_share->fields; @@ -1732,7 +1732,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf, int res; DBUG_ENTER("pk_read"); DBUG_PRINT("enter", ("key_len: %u", key_len)); - DBUG_DUMP("key", (char*)key, key_len); + DBUG_DUMP("key", key, key_len); m_write_op= FALSE; NdbOperation::LockMode lm= @@ -1745,7 +1745,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf, { // This table has no primary key, use "hidden" primary key DBUG_PRINT("info", ("Using hidden key")); - DBUG_DUMP("key", (char*)key, 8); + DBUG_DUMP("key", key, 8); if (set_hidden_key(op, no_fields, key)) ERR_RETURN(trans->getNdbError()); @@ -1791,7 +1791,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf, or hidden key */ -int ha_ndbcluster::complemented_read(const byte *old_data, byte *new_data, +int ha_ndbcluster::complemented_read(const uchar *old_data, uchar *new_data, uint32 old_part_id) { uint no_fields= table_share->fields, i; @@ -1928,7 +1928,7 @@ bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans, */ static int -check_null_in_record(const KEY* key_info, const byte *record) +check_null_in_record(const KEY* key_info, const uchar *record) { KEY_PART_INFO *curr_part, *end_part; curr_part= key_info->key_part; @@ -1955,7 +1955,7 @@ check_null_in_record(const KEY* key_info, const byte *record) * primary key or unique index values */ -int ha_ndbcluster::peek_indexed_rows(const byte *record, +int ha_ndbcluster::peek_indexed_rows(const uchar *record, bool check_pk) { NdbTransaction *trans= m_active_trans; @@ -2059,15 +2059,15 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, Read one record from NDB using unique secondary index */ -int ha_ndbcluster::unique_index_read(const byte *key, - uint key_len, byte *buf) +int ha_ndbcluster::unique_index_read(const uchar *key, + uint key_len, uchar *buf) { int res; NdbTransaction *trans= m_active_trans; NdbIndexOperation *op; DBUG_ENTER("ha_ndbcluster::unique_index_read"); DBUG_PRINT("enter", ("key_len: %u, index: %u", key_len, active_index)); - DBUG_DUMP("key", (char*)key, key_len); + DBUG_DUMP("key", key, key_len); NdbOperation::LockMode lm= (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); @@ -2203,7 +2203,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor) */ -inline int ha_ndbcluster::next_result(byte *buf) +inline int ha_ndbcluster::next_result(uchar *buf) { int res; DBUG_ENTER("next_result"); @@ -2282,10 +2282,10 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, struct part_st { bool part_last; const key_range *key; - const byte *part_ptr; + const uchar *part_ptr; bool part_null; int bound_type; - const char* bound_ptr; + const uchar* bound_ptr; }; struct part_st part[2]; @@ -2395,13 +2395,13 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, { DBUG_PRINT("info", ("key %d:%d offset: %d length: %d last: %d bound: %d", j, i, tot_len, part_len, p.part_last, p.bound_type)); - DBUG_DUMP("info", (const char*)p.part_ptr, part_store_len); + DBUG_DUMP("info", p.part_ptr, part_store_len); // Set bound if not cancelled via type -1 if (p.bound_type != -1) { - const char* ptr= p.bound_ptr; - char buf[256]; + const uchar* ptr= p.bound_ptr; + uchar buf[256]; shrink_varchar(field, ptr, buf); if (op->setBound(i, p.bound_type, ptr)) ERR_RETURN(op->getNdbError()); @@ -2421,7 +2421,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, int ha_ndbcluster::ordered_index_scan(const key_range *start_key, const key_range *end_key, bool sorted, bool descending, - byte* buf, part_id_range *part_spec) + uchar* buf, part_id_range *part_spec) { int res; bool restart; @@ -2527,9 +2527,9 @@ guess_scan_flags(NdbOperation::LockMode lm, */ int ha_ndbcluster::unique_index_scan(const KEY* key_info, - const byte *key, + const uchar *key, uint key_len, - byte *buf) + uchar *buf) { int res; NdbScanOperation *op; @@ -2603,7 +2603,7 @@ int ha_ndbcluster::unique_index_scan(const KEY* key_info, Start full table scan in NDB */ -int ha_ndbcluster::full_table_scan(byte *buf) +int ha_ndbcluster::full_table_scan(uchar *buf) { int res; NdbScanOperation *op; @@ -2670,7 +2670,7 @@ int ha_ndbcluster::full_table_scan(byte *buf) /* Insert one record into NDB */ -int ha_ndbcluster::write_row(byte *record) +int ha_ndbcluster::write_row(uchar *record) { bool has_auto_increment; uint i; @@ -2757,17 +2757,17 @@ int ha_ndbcluster::write_row(byte *record) Ndb_tuple_id_range_guard g(m_share); if (ndb->getAutoIncrementValue(m_table, g.range, auto_value, 1) == -1) { - if (--retries && - ndb->getNdbError().status == NdbError::TemporaryError); - { - my_sleep(retry_sleep); - continue; - } - ERR_RETURN(ndb->getNdbError()); + if (--retries && + ndb->getNdbError().status == NdbError::TemporaryError); + { + my_sleep(retry_sleep); + continue; + } + ERR_RETURN(ndb->getNdbError()); } break; } - if (set_hidden_key(op, table->s->fields, (const byte*)&auto_value)) + if (set_hidden_key(op, table_share->fields, (const uchar*)&auto_value)) ERR_RETURN(op->getNdbError()); } else @@ -2812,7 +2812,8 @@ int ha_ndbcluster::write_row(byte *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -2888,8 +2889,8 @@ int ha_ndbcluster::write_row(byte *record) /* Compare if a key in a row has changed */ -int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row, - const byte * new_row) +int ha_ndbcluster::key_cmp(uint keynr, const uchar * old_row, + const uchar * new_row) { KEY_PART_INFO *key_part=table->key_info[keynr].key_part; KEY_PART_INFO *end=key_part+table->key_info[keynr].key_parts; @@ -2905,8 +2906,8 @@ int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row, if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART)) { - if (key_part->field->cmp_binary((char*) (old_row + key_part->offset), - (char*) (new_row + key_part->offset), + if (key_part->field->cmp_binary((old_row + key_part->offset), + (new_row + key_part->offset), (ulong) key_part->length)) return 1; } @@ -2924,7 +2925,7 @@ int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row, Update one record in NDB using primary key */ -int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) +int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) { THD *thd= table->in_use; NdbTransaction *trans= m_active_trans; @@ -3010,7 +3011,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) { // Undo delete_row(old_data) m_primary_key_update= TRUE; - undo_res= write_row((byte *)old_data); + undo_res= write_row((uchar *)old_data); if (undo_res) push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -3101,7 +3102,8 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -3125,7 +3127,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) Delete one record from NDB, using primary key */ -int ha_ndbcluster::delete_row(const byte *record) +int ha_ndbcluster::delete_row(const uchar *record) { THD *thd= table->in_use; NdbTransaction *trans= m_active_trans; @@ -3168,7 +3170,8 @@ int ha_ndbcluster::delete_row(const byte *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) ((NdbOperation *)trans->getLastDefinedOperation())-> setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) @@ -3207,7 +3210,8 @@ int ha_ndbcluster::delete_row(const byte *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -3237,7 +3241,7 @@ int ha_ndbcluster::delete_row(const byte *record) */ void ndb_unpack_record(TABLE *table, NdbValue *value, - MY_BITMAP *defined, byte *buf) + MY_BITMAP *defined, uchar *buf) { Field **p_field= table->field, *field= *p_field; my_ptrdiff_t row_offset= (my_ptrdiff_t) (buf - table->record[0]); @@ -3324,13 +3328,13 @@ void ndb_unpack_record(TABLE *table, NdbValue *value, field_bit->Field_bit::move_field_offset(-row_offset); DBUG_PRINT("info",("[%u] SET", (*value).rec->getColumn()->getColumnNo())); - DBUG_DUMP("info", (const char*) field->ptr, field->pack_length()); + DBUG_DUMP("info", field->ptr, field->pack_length()); } else { DBUG_PRINT("info",("[%u] SET", (*value).rec->getColumn()->getColumnNo())); - DBUG_DUMP("info", (const char*) field->ptr, field->pack_length()); + DBUG_DUMP("info", field->ptr, field->pack_length()); } } else @@ -3354,7 +3358,7 @@ void ndb_unpack_record(TABLE *table, NdbValue *value, #ifndef DBUG_OFF // pointer vas set in get_ndb_blobs_value Field_blob *field_blob= (Field_blob*)field; - char* ptr; + uchar *ptr; field_blob->get_ptr(&ptr, row_offset); uint32 len= field_blob->get_length(row_offset); DBUG_PRINT("info",("[%u] SET ptr: 0x%lx len: %u", @@ -3368,7 +3372,7 @@ void ndb_unpack_record(TABLE *table, NdbValue *value, DBUG_VOID_RETURN; } -void ha_ndbcluster::unpack_record(byte *buf) +void ha_ndbcluster::unpack_record(uchar *buf) { ndb_unpack_record(table, m_value, 0, buf); #ifndef DBUG_OFF @@ -3481,10 +3485,10 @@ int ha_ndbcluster::index_end() */ static int -check_null_in_key(const KEY* key_info, const byte *key, uint key_len) +check_null_in_key(const KEY* key_info, const uchar *key, uint key_len) { KEY_PART_INFO *curr_part, *end_part; - const byte* end_ptr= key + key_len; + const uchar* end_ptr= key + key_len; curr_part= key_info->key_part; end_part= curr_part + key_info->key_parts; @@ -3498,8 +3502,8 @@ check_null_in_key(const KEY* key_info, const byte *key, uint key_len) return 0; } -int ha_ndbcluster::index_read(byte *buf, - const byte *key, uint key_len, +int ha_ndbcluster::index_read(uchar *buf, + const uchar *key, uint key_len, enum ha_rkey_function find_flag) { key_range start_key; @@ -3527,7 +3531,7 @@ int ha_ndbcluster::index_read(byte *buf, } -int ha_ndbcluster::index_next(byte *buf) +int ha_ndbcluster::index_next(uchar *buf) { DBUG_ENTER("ha_ndbcluster::index_next"); ha_statistic_increment(&SSV::ha_read_next_count); @@ -3535,7 +3539,7 @@ int ha_ndbcluster::index_next(byte *buf) } -int ha_ndbcluster::index_prev(byte *buf) +int ha_ndbcluster::index_prev(uchar *buf) { DBUG_ENTER("ha_ndbcluster::index_prev"); ha_statistic_increment(&SSV::ha_read_prev_count); @@ -3543,7 +3547,7 @@ int ha_ndbcluster::index_prev(byte *buf) } -int ha_ndbcluster::index_first(byte *buf) +int ha_ndbcluster::index_first(uchar *buf) { DBUG_ENTER("ha_ndbcluster::index_first"); ha_statistic_increment(&SSV::ha_read_first_count); @@ -3554,14 +3558,14 @@ int ha_ndbcluster::index_first(byte *buf) } -int ha_ndbcluster::index_last(byte *buf) +int ha_ndbcluster::index_last(uchar *buf) { DBUG_ENTER("ha_ndbcluster::index_last"); ha_statistic_increment(&SSV::ha_read_last_count); DBUG_RETURN(ordered_index_scan(0, 0, TRUE, TRUE, buf, NULL)); } -int ha_ndbcluster::index_read_last(byte * buf, const byte * key, uint key_len) +int ha_ndbcluster::index_read_last(uchar * buf, const uchar * key, uint key_len) { DBUG_ENTER("ha_ndbcluster::index_read_last"); DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST)); @@ -3570,7 +3574,7 @@ int ha_ndbcluster::index_read_last(byte * buf, const byte * key, uint key_len) int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, const key_range *end_key, bool desc, bool sorted, - byte* buf) + uchar* buf) { part_id_range part_spec; ndb_index_type type= get_index_type(active_index); @@ -3650,7 +3654,7 @@ int ha_ndbcluster::read_range_first(const key_range *start_key, const key_range *end_key, bool eq_r, bool sorted) { - byte* buf= table->record[0]; + uchar* buf= table->record[0]; DBUG_ENTER("ha_ndbcluster::read_range_first"); DBUG_RETURN(read_range_first_to_buf(start_key, end_key, FALSE, sorted, buf)); @@ -3740,7 +3744,7 @@ int ha_ndbcluster::rnd_end() } -int ha_ndbcluster::rnd_next(byte *buf) +int ha_ndbcluster::rnd_next(uchar *buf) { DBUG_ENTER("rnd_next"); ha_statistic_increment(&SSV::ha_read_rnd_next_count); @@ -3758,7 +3762,7 @@ int ha_ndbcluster::rnd_next(byte *buf) again */ -int ha_ndbcluster::rnd_pos(byte *buf, byte *pos) +int ha_ndbcluster::rnd_pos(uchar *buf, uchar *pos) { DBUG_ENTER("rnd_pos"); ha_statistic_increment(&SSV::ha_read_rnd_count); @@ -3775,7 +3779,7 @@ int ha_ndbcluster::rnd_pos(byte *buf, byte *pos) The partition id has been fetched from ndb and has been stored directly after the hidden key */ - DBUG_DUMP("key+part", (char *)pos, key_length); + DBUG_DUMP("key+part", pos, key_length); key_length= ref_length - sizeof(m_part_id); part_spec.start_part= part_spec.end_part= *(uint32 *)(pos + key_length); } @@ -3792,7 +3796,7 @@ int ha_ndbcluster::rnd_pos(byte *buf, byte *pos) } DBUG_PRINT("info", ("partition id %u", part_spec.start_part)); } - DBUG_DUMP("key", (char *)pos, key_length); + DBUG_DUMP("key", pos, key_length); DBUG_RETURN(pk_read(pos, key_length, buf, part_spec.start_part)); } } @@ -3804,12 +3808,12 @@ int ha_ndbcluster::rnd_pos(byte *buf, byte *pos) using "reference" in rnd_pos */ -void ha_ndbcluster::position(const byte *record) +void ha_ndbcluster::position(const uchar *record) { KEY *key_info; KEY_PART_INFO *key_part; KEY_PART_INFO *end; - byte *buff; + uchar *buff; uint key_length; DBUG_ENTER("position"); @@ -3835,7 +3839,7 @@ void ha_ndbcluster::position(const byte *record) } size_t len = key_part->length; - const byte * ptr = record + key_part->offset; + const uchar * ptr = record + key_part->offset; Field *field = key_part->field; if (field->type() == MYSQL_TYPE_VARCHAR) { @@ -3886,9 +3890,9 @@ void ha_ndbcluster::position(const byte *record) } #ifndef DBUG_OFF if (table_share->primary_key == MAX_KEY && m_use_partition_function) - DBUG_DUMP("key+part", (char*)ref, key_length+sizeof(m_part_id)); + DBUG_DUMP("key+part", ref, key_length+sizeof(m_part_id)); #endif - DBUG_DUMP("ref", (char*)ref, key_length); + DBUG_DUMP("ref", ref, key_length); DBUG_VOID_RETURN; } @@ -4385,8 +4389,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) thd_ndb->query_state&= NDB_QUERY_NORMAL; thd_ndb->trans_options= 0; thd_ndb->m_slow_path= FALSE; - if (thd->slave_thread || - !(thd->options & OPTION_BIN_LOG)) + if (!(thd->options & OPTION_BIN_LOG) || + thd->variables.binlog_format == BINLOG_FORMAT_STMT) + { + thd_ndb->trans_options|= TNTO_NO_LOGGING; + thd_ndb->m_slow_path= TRUE; + } + else if (thd->slave_thread) thd_ndb->m_slow_path= TRUE; trans_register_ha(thd, FALSE, ndbcluster_hton); } @@ -4406,8 +4415,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) thd_ndb->query_state&= NDB_QUERY_NORMAL; thd_ndb->trans_options= 0; thd_ndb->m_slow_path= FALSE; - if (thd->slave_thread || - !(thd->options & OPTION_BIN_LOG)) + if (!(thd->options & OPTION_BIN_LOG) || + thd->variables.binlog_format == BINLOG_FORMAT_STMT) + { + thd_ndb->trans_options|= TNTO_NO_LOGGING; + thd_ndb->m_slow_path= TRUE; + } + else if (thd->slave_thread) thd_ndb->m_slow_path= TRUE; trans_register_ha(thd, TRUE, ndbcluster_hton); @@ -4526,7 +4540,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("warning", ("ops_pending != 0L")); m_ops_pending= 0; } - thd->set_current_stmt_binlog_row_based_if_mixed(); DBUG_RETURN(error); } @@ -4576,7 +4589,6 @@ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type) m_active_trans= trans; // Start of statement m_ops_pending= 0; - thd->set_current_stmt_binlog_row_based_if_mixed(); DBUG_RETURN(error); } @@ -4989,8 +5001,9 @@ int ha_ndbcluster::create(const char *name, THD *thd= current_thd; NDBTAB tab; NDBCOL col; - uint pack_length, length, i, pk_length= 0; - const void *data= NULL, *pack_data= NULL; + size_t pack_length, length; + uint i, pk_length= 0; + uchar *data= NULL, *pack_data= NULL; bool create_from_engine= (create_info->table_options & HA_OPTION_CREATE_FROM_ENGINE); bool is_truncate= (thd->lex->sql_command == SQLCOM_TRUNCATE); char tablespace[FN_LEN]; @@ -5074,7 +5087,9 @@ int ha_ndbcluster::create(const char *name, my_free((char*)data, MYF(0)); DBUG_RETURN(2); } - DBUG_PRINT("info", ("setFrm data: 0x%lx len: %d", (long) pack_data, pack_length)); + DBUG_PRINT("info", + ("setFrm data: 0x%lx len: %lu", (long) pack_data, + (ulong) pack_length)); tab.setFrm(pack_data, pack_length); my_free((char*)data, MYF(0)); my_free((char*)pack_data, MYF(0)); @@ -5309,7 +5324,7 @@ int ha_ndbcluster::create(const char *name, { uint length= (uint) strlen(name); if ((share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables, - (byte*) name, length))) + (uchar*) name, length))) handle_trailing_share(share); } /* @@ -5388,8 +5403,8 @@ int ha_ndbcluster::create_handler_files(const char *file, { Ndb* ndb; const NDBTAB *tab; - const void *data= NULL, *pack_data= NULL; - uint length, pack_length; + uchar *data= NULL, *pack_data= NULL; + size_t length, pack_length; int error= 0; DBUG_ENTER("create_handler_files"); @@ -6125,6 +6140,11 @@ void ha_ndbcluster::get_auto_increment(ulonglong offset, ulonglong increment, Constructor for the NDB Cluster table handler */ +/* + Normal flags for binlogging is that ndb has HA_HAS_OWN_BINLOGGING + and preferes HA_BINLOG_ROW_CAPABLE + Other flags are set under certain circumstaces in table_flags() +*/ #define HA_NDBCLUSTER_TABLE_FLAGS \ HA_REC_NOT_IN_SEQ | \ HA_NULL_IN_KEY | \ @@ -6137,6 +6157,7 @@ void ha_ndbcluster::get_auto_increment(ulonglong offset, ulonglong increment, HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | \ HA_PARTIAL_COLUMN_READ | \ HA_HAS_OWN_BINLOGGING | \ + HA_BINLOG_ROW_CAPABLE | \ HA_HAS_RECORDS ha_ndbcluster::ha_ndbcluster(handlerton *hton, TABLE_SHARE *table_arg): @@ -6469,13 +6490,13 @@ static int ndbcluster_close_connection(handlerton *hton, THD *thd) int ndbcluster_discover(handlerton *hton, THD* thd, const char *db, const char *name, - const void** frmblob, - uint* frmlen) + uchar **frmblob, + size_t *frmlen) { int error= 0; NdbError ndb_error; - uint len; - const void* data= NULL; + size_t len; + uchar* data= NULL; Ndb* ndb; char key[FN_REFLEN]; DBUG_ENTER("ndbcluster_discover"); @@ -6536,7 +6557,7 @@ int ndbcluster_discover(handlerton *hton, THD* thd, const char *db, goto err; } - if (unpackfrm(&data, &len, tab->getFrmData())) + if (unpackfrm(&data, &len, (uchar*) tab->getFrmData())) { DBUG_PRINT("error", ("Could not unpack table")); error= 1; @@ -6606,11 +6627,11 @@ int ndbcluster_table_exists_in_engine(handlerton *hton, THD* thd, -extern "C" byte* tables_get_key(const char *entry, uint *length, +extern "C" uchar* tables_get_key(const char *entry, size_t *length, my_bool not_used __attribute__((unused))) { *length= strlen(entry); - return (byte*) entry; + return (uchar*) entry; } @@ -6791,8 +6812,8 @@ int ndbcluster_find_all_files(THD *thd) /* finalize construction of path */ end+= tablename_to_filename(elmt.name, end, sizeof(key)-(end-key)); - const void *data= 0, *pack_data= 0; - uint length, pack_length; + uchar *data= 0, *pack_data= 0; + size_t length, pack_length; int discover= 0; if (readfrm(key, &data, &length) || packfrm(data, length, &pack_data, &pack_length)) @@ -6920,7 +6941,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, continue; } DBUG_PRINT("info", ("Inserting %s into ndb_tables hash", elmt.name)); - my_hash_insert(&ndb_tables, (byte*)thd->strdup(elmt.name)); + my_hash_insert(&ndb_tables, (uchar*)thd->strdup(elmt.name)); } char *file_name; @@ -6930,7 +6951,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, { bool file_on_disk= FALSE; DBUG_PRINT("info", ("%s", file_name)); - if (hash_search(&ndb_tables, file_name, strlen(file_name))) + if (hash_search(&ndb_tables, (uchar*) file_name, strlen(file_name))) { DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name)); file_on_disk= TRUE; @@ -6946,7 +6967,8 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, if (file_on_disk) { // Ignore this ndb table - gptr record= hash_search(&ndb_tables, file_name, strlen(file_name)); + uchar *record= hash_search(&ndb_tables, (uchar*) file_name, + strlen(file_name)); DBUG_ASSERT(record); hash_delete(&ndb_tables, record); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -6959,7 +6981,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, if (file_on_disk) { // File existed in NDB and as frm file, put in ok_tables list - my_hash_insert(&ok_tables, (byte*)file_name); + my_hash_insert(&ok_tables, (uchar*)file_name); continue; } DBUG_PRINT("info", ("%s existed on disk", name)); @@ -6997,8 +7019,8 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, List<char> create_list; for (i= 0 ; i < ndb_tables.records ; i++) { - file_name= hash_element(&ndb_tables, i); - if (!hash_search(&ok_tables, file_name, strlen(file_name))) + file_name= (char*) hash_element(&ndb_tables, i); + if (!hash_search(&ok_tables, (uchar*) file_name, strlen(file_name))) { build_table_filename(name, sizeof(name), db, file_name, reg_ext, 0); if (my_access(name, F_OK)) @@ -7562,9 +7584,17 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key, ulonglong ha_ndbcluster::table_flags(void) const { + THD *thd= current_thd; + ulonglong f= m_table_flags; if (m_ha_not_exact_count) - return m_table_flags & ~HA_STATS_RECORDS_IS_EXACT; - return m_table_flags; + f= f & ~HA_STATS_RECORDS_IS_EXACT; + /* + To allow for logging of ndb tables during stmt based logging; + flag cabablity, but also turn off flag for OWN_BINLOGGING + */ + if (thd->variables.binlog_format == BINLOG_FORMAT_STMT) + f= (f | HA_BINLOG_STMT_CAPABLE) & ~HA_HAS_OWN_BINLOGGING; + return f; } const char * ha_ndbcluster::table_type() const { @@ -7630,7 +7660,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, DBUG_PRINT("enter", ("name: %s", name)); pthread_mutex_lock(&ndbcluster_mutex); if (!(share=(NDB_SHARE*) hash_search(&ndbcluster_open_tables, - (byte*) name, + (uchar*) name, strlen(name)))) { pthread_mutex_unlock(&ndbcluster_mutex); @@ -7855,11 +7885,11 @@ ha_ndbcluster::register_query_cache_table(THD *thd, data we want to or can share. */ -static byte *ndbcluster_get_key(NDB_SHARE *share,uint *length, +static uchar *ndbcluster_get_key(NDB_SHARE *share, size_t *length, my_bool not_used __attribute__((unused))) { *length= share->key_length; - return (byte*) share->key; + return (uchar*) share->key; } @@ -8002,7 +8032,7 @@ int handle_trailing_share(NDB_SHARE *share) at the cost of a possible mem leak, by "renaming" the share - First remove from hash */ - hash_delete(&ndbcluster_open_tables, (byte*) share); + hash_delete(&ndbcluster_open_tables, (uchar*) share); /* now give it a new name, just a running number @@ -8012,7 +8042,7 @@ int handle_trailing_share(NDB_SHARE *share) const uint min_key_length= 10; if (share->key_length < min_key_length) { - share->key= alloc_root(&share->mem_root, min_key_length + 1); + share->key= (char*) alloc_root(&share->mem_root, min_key_length + 1); share->key_length= min_key_length; } share->key_length= @@ -8020,7 +8050,7 @@ int handle_trailing_share(NDB_SHARE *share) trailing_share_id++); } /* Keep it for possible the future trailing free */ - my_hash_insert(&ndbcluster_open_tables, (byte*) share); + my_hash_insert(&ndbcluster_open_tables, (uchar*) share); DBUG_RETURN(0); } @@ -8036,11 +8066,11 @@ static int rename_share(NDB_SHARE *share, const char *new_key) DBUG_PRINT("rename_share", ("old_key: %s old__length: %d", share->key, share->key_length)); if ((tmp= (NDB_SHARE*) hash_search(&ndbcluster_open_tables, - (byte*) new_key, new_length))) + (uchar*) new_key, new_length))) handle_trailing_share(tmp); /* remove the share from hash */ - hash_delete(&ndbcluster_open_tables, (byte*) share); + hash_delete(&ndbcluster_open_tables, (uchar*) share); dbug_print_open_tables(); /* save old stuff if insert should fail */ @@ -8051,18 +8081,18 @@ static int rename_share(NDB_SHARE *share, const char *new_key) now allocate and set the new key, db etc enough space for key, db, and table_name */ - share->key= alloc_root(&share->mem_root, 2 * (new_length + 1)); + share->key= (char*) alloc_root(&share->mem_root, 2 * (new_length + 1)); strmov(share->key, new_key); share->key_length= new_length; - if (my_hash_insert(&ndbcluster_open_tables, (byte*) share)) + if (my_hash_insert(&ndbcluster_open_tables, (uchar*) share)) { // ToDo free the allocated stuff above? DBUG_PRINT("error", ("rename_share: my_hash_insert %s failed", share->key)); share->key= old_key; share->key_length= old_length; - if (my_hash_insert(&ndbcluster_open_tables, (byte*) share)) + if (my_hash_insert(&ndbcluster_open_tables, (uchar*) share)) { sql_print_error("rename_share: failed to recover %s", share->key); DBUG_PRINT("error", ("rename_share: my_hash_insert %s failed", @@ -8142,7 +8172,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, if (!have_lock) pthread_mutex_lock(&ndbcluster_mutex); if (!(share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables, - (byte*) key, + (uchar*) key, length))) { if (!create_if_not_exists) @@ -8162,13 +8192,13 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, *root_ptr= &share->mem_root; // remember to reset before return share->state= NSS_INITIAL; /* enough space for key, db, and table_name */ - share->key= alloc_root(*root_ptr, 2 * (length + 1)); + share->key= (char*) alloc_root(*root_ptr, 2 * (length + 1)); share->key_length= length; strmov(share->key, key); - if (my_hash_insert(&ndbcluster_open_tables, (byte*) share)) + if (my_hash_insert(&ndbcluster_open_tables, (uchar*) share)) { free_root(&share->mem_root, MYF(0)); - my_free((gptr) share, 0); + my_free((uchar*) share, 0); *root_ptr= old_root; if (!have_lock) pthread_mutex_unlock(&ndbcluster_mutex); @@ -8211,7 +8241,7 @@ void ndbcluster_real_free_share(NDB_SHARE **share) DBUG_ENTER("ndbcluster_real_free_share"); dbug_print_share("ndbcluster_real_free_share:", *share); - hash_delete(&ndbcluster_open_tables, (byte*) *share); + hash_delete(&ndbcluster_open_tables, (uchar*) *share); thr_lock_delete(&(*share)->lock); pthread_mutex_destroy(&(*share)->mutex); @@ -8223,15 +8253,15 @@ void ndbcluster_real_free_share(NDB_SHARE **share) // (*share)->table_share->mem_root is freed by free_table_share free_table_share((*share)->table_share); #ifndef DBUG_OFF - bzero((gptr)(*share)->table_share, sizeof(*(*share)->table_share)); - bzero((gptr)(*share)->table, sizeof(*(*share)->table)); + bzero((uchar*)(*share)->table_share, sizeof(*(*share)->table_share)); + bzero((uchar*)(*share)->table, sizeof(*(*share)->table)); (*share)->table_share= 0; (*share)->table= 0; #endif } #endif free_root(&(*share)->mem_root, MYF(0)); - my_free((gptr) *share, MYF(0)); + my_free((uchar*) *share, MYF(0)); *share= 0; dbug_print_open_tables(); @@ -8457,13 +8487,13 @@ ha_ndbcluster::null_value_index_search(KEY_MULTI_RANGE *ranges, KEY* key_info= table->key_info + active_index; KEY_MULTI_RANGE *range= ranges; ulong reclength= table->s->reclength; - byte *curr= (byte*)buffer->buffer; - byte *end_of_buffer= (byte*)buffer->buffer_end; + uchar *curr= (uchar*)buffer->buffer; + uchar *end_of_buffer= (uchar*)buffer->buffer_end; for (; range<end_range && curr+reclength <= end_of_buffer; range++) { - const byte *key= range->start_key.key; + const uchar *key= range->start_key.key; uint key_len= range->start_key.length; if (check_null_in_key(key_info, key, key_len)) DBUG_RETURN(TRUE); @@ -8531,8 +8561,8 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, /** * Variables for loop */ - byte *curr= (byte*)buffer->buffer; - byte *end_of_buffer= (byte*)buffer->buffer_end; + uchar *curr= (uchar*)buffer->buffer; + uchar *end_of_buffer= (uchar*)buffer->buffer_end; NdbOperation::LockMode lm= (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); bool need_pk = (lm == NdbOperation::LM_Read); @@ -8661,7 +8691,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, * This as we don't want mysqld to reuse the buffer when we read * the remaining ranges */ - buffer->end_of_used_area= (byte*)buffer->buffer_end; + buffer->end_of_used_area= (uchar*)buffer->buffer_end; } else { @@ -8677,7 +8707,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, { m_multi_range_defined= multi_range_curr; multi_range_curr= ranges; - m_multi_range_result_ptr= (byte*)buffer->buffer; + m_multi_range_result_ptr= (uchar*)buffer->buffer; DBUG_RETURN(read_multi_range_next(found_range_p)); } ERR_RETURN(m_active_trans->getNdbError()); @@ -8896,7 +8926,7 @@ ha_ndbcluster::update_table_comment( char *str; const char *fmt="%s%snumber_of_replicas: %d"; const unsigned fmt_len_plus_extra= length + strlen(fmt); - if ((str= my_malloc(fmt_len_plus_extra, MYF(0))) == NULL) + if ((str= (char*) my_malloc(fmt_len_plus_extra, MYF(0))) == NULL) { sql_print_error("ha_ndbcluster::update_table_comment: " "my_malloc(%u) failed", (unsigned int)fmt_len_plus_extra); @@ -8945,7 +8975,6 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) my_net_init(&thd->net, 0); thd->main_security_ctx.master_access= ~0; thd->main_security_ctx.priv_user = 0; - thd->current_stmt_binlog_row_based= TRUE; // If in mixed mode CHARSET_INFO *charset_connection; charset_connection= get_charset_by_csname("utf8", diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 591745076a1..4f5a1359d2d 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -84,7 +84,7 @@ typedef struct ndb_index_data { typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue; int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, - byte*& buffer, uint& buffer_size, + uchar*& buffer, uint& buffer_size, my_ptrdiff_t ptrdiff); typedef enum { @@ -115,7 +115,7 @@ typedef struct st_ndbcluster_share { char *old_names; // for rename table TABLE_SHARE *table_share; TABLE *table; - byte *record[2]; // pointer to allocated records for receiving data + uchar *record[2]; // pointer to allocated records for receiving data NdbValue *ndb_value[2]; MY_BITMAP *subscriber_bitmap; #endif @@ -178,6 +178,7 @@ enum THD_NDB_OPTIONS enum THD_NDB_TRANS_OPTIONS { TNTO_INJECTED_APPLY_STATUS= 1 << 0 + ,TNTO_NO_LOGGING= 1 << 1 }; struct Ndb_local_table_statistics { @@ -226,30 +227,30 @@ class ha_ndbcluster: public handler int open(const char *name, int mode, uint test_if_locked); int close(void); - int write_row(byte *buf); - int update_row(const byte *old_data, byte *new_data); - int delete_row(const byte *buf); + int write_row(uchar *buf); + int update_row(const uchar *old_data, uchar *new_data); + int delete_row(const uchar *buf); int index_init(uint index, bool sorted); int index_end(); - int index_read(byte *buf, const byte *key, uint key_len, + int index_read(uchar *buf, const uchar *key, uint key_len, enum ha_rkey_function find_flag); - int index_next(byte *buf); - int index_prev(byte *buf); - int index_first(byte *buf); - int index_last(byte *buf); - int index_read_last(byte * buf, const byte * key, uint key_len); + int index_next(uchar *buf); + int index_prev(uchar *buf); + int index_first(uchar *buf); + int index_last(uchar *buf); + int index_read_last(uchar * buf, const uchar * key, uint key_len); int rnd_init(bool scan); int rnd_end(); - int rnd_next(byte *buf); - int rnd_pos(byte *buf, byte *pos); - void position(const byte *record); + int rnd_next(uchar *buf); + int rnd_pos(uchar *buf, uchar *pos); + void position(const uchar *record); int read_range_first(const key_range *start_key, const key_range *end_key, bool eq_range, bool sorted); int read_range_first_to_buf(const key_range *start_key, const key_range *end_key, bool eq_range, bool sorted, - byte* buf); + uchar* buf); int read_range_next(); int alter_tablespace(st_alter_tablespace *info); @@ -418,56 +419,56 @@ private: char* get_tablespace_name(THD *thd, char *name, uint name_len); int set_range_data(void *tab, partition_info* part_info); int set_list_data(void *tab, partition_info* part_info); - int complemented_read(const byte *old_data, byte *new_data, + int complemented_read(const uchar *old_data, uchar *new_data, uint32 old_part_id); - int pk_read(const byte *key, uint key_len, byte *buf, uint32 part_id); + int pk_read(const uchar *key, uint key_len, uchar *buf, uint32 part_id); int ordered_index_scan(const key_range *start_key, const key_range *end_key, - bool sorted, bool descending, byte* buf, + bool sorted, bool descending, uchar* buf, part_id_range *part_spec); - int unique_index_read(const byte *key, uint key_len, - byte *buf); + int unique_index_read(const uchar *key, uint key_len, + uchar *buf); int unique_index_scan(const KEY* key_info, - const byte *key, + const uchar *key, uint key_len, - byte *buf); - int full_table_scan(byte * buf); + uchar *buf); + int full_table_scan(uchar * buf); bool check_all_operations_for_error(NdbTransaction *trans, const NdbOperation *first, const NdbOperation *last, uint errcode); - int peek_indexed_rows(const byte *record, bool check_pk); + int peek_indexed_rows(const uchar *record, bool check_pk); int fetch_next(NdbScanOperation* op); - int next_result(byte *buf); - int define_read_attrs(byte* buf, NdbOperation* op); - int filtered_scan(const byte *key, uint key_len, - byte *buf, + int next_result(uchar *buf); + int define_read_attrs(uchar* buf, NdbOperation* op); + int filtered_scan(const uchar *key, uint key_len, + uchar *buf, enum ha_rkey_function find_flag); int close_scan(); - void unpack_record(byte *buf); + void unpack_record(uchar *buf); int get_ndb_lock_type(enum thr_lock_type type); void set_dbname(const char *pathname); void set_tabname(const char *pathname); bool set_hidden_key(NdbOperation*, - uint fieldnr, const byte* field_ptr); + uint fieldnr, const uchar* field_ptr); int set_ndb_key(NdbOperation*, Field *field, - uint fieldnr, const byte* field_ptr); + uint fieldnr, const uchar* field_ptr); int set_ndb_value(NdbOperation*, Field *field, uint fieldnr, int row_offset= 0, bool *set_blob_value= 0); - int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, byte*); + int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, uchar*); int get_ndb_partition_id(NdbOperation *); friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg); - int set_primary_key(NdbOperation *op, const byte *key); - int set_primary_key_from_record(NdbOperation *op, const byte *record); - int set_index_key_from_record(NdbOperation *op, const byte *record, + int set_primary_key(NdbOperation *op, const uchar *key); + int set_primary_key_from_record(NdbOperation *op, const uchar *record); + int set_index_key_from_record(NdbOperation *op, const uchar *record, uint keyno); int set_bounds(NdbIndexScanOperation*, uint inx, bool rir, const key_range *keys[2], uint= 0); - int key_cmp(uint keynr, const byte * old_row, const byte * new_row); - int set_index_key(NdbOperation *, const KEY *key_info, const byte *key_ptr); + int key_cmp(uint keynr, const uchar * old_row, const uchar * new_row); + int set_index_key(NdbOperation *, const KEY *key_info, const uchar *key_ptr); void print_results(); virtual void get_auto_increment(ulonglong offset, ulonglong increment, @@ -510,10 +511,10 @@ private: THD_NDB_SHARE *m_thd_ndb_share; // NdbRecAttr has no reference to blob NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE]; - byte m_ref[NDB_HIDDEN_PRIMARY_KEY_LENGTH]; + uchar m_ref[NDB_HIDDEN_PRIMARY_KEY_LENGTH]; partition_info *m_part_info; uint32 m_part_id; - byte *m_rec0; + uchar *m_rec0; Field **m_part_field_array; bool m_use_partition_function; bool m_sorted; @@ -536,7 +537,7 @@ private: bool m_slow_path; my_ptrdiff_t m_blobs_offset; // memory for blobs in one tuple - char *m_blobs_buffer; + uchar *m_blobs_buffer; uint32 m_blobs_buffer_size; uint m_dupkey; // set from thread variables at external lock @@ -547,12 +548,12 @@ private: ha_ndbcluster_cond *m_cond; bool m_disable_multi_read; - byte *m_multi_range_result_ptr; + uchar *m_multi_range_result_ptr; KEY_MULTI_RANGE *m_multi_ranges; KEY_MULTI_RANGE *m_multi_range_defined; const NdbOperation *m_current_multi_operation; NdbIndexScanOperation *m_multi_cursor; - byte *m_multi_range_cursor_result_ptr; + uchar *m_multi_range_cursor_result_ptr; int setup_recattr(const NdbRecAttr*); Ndb *get_ndb(); }; diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 987d217873b..f388b60f3d5 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -144,14 +144,14 @@ static TABLE_LIST binlog_tables; #ifndef DBUG_OFF /* purecov: begin deadcode */ -static void print_records(TABLE *table, const char *record) +static void print_records(TABLE *table, const uchar *record) { for (uint j= 0; j < table->s->fields; j++) { char buf[40]; int pos= 0; Field *field= table->field[j]; - const byte* field_ptr= field->ptr - table->record[0] + record; + const uchar* field_ptr= field->ptr - table->record[0] + record; int pack_len= field->pack_length(); int n= pack_len < 10 ? pack_len : 10; @@ -210,14 +210,14 @@ static void dbug_print_table(const char *info, TABLE *table) (long) f->ptr, (int) (f->ptr - table->record[0]), f->null_bit, (long) f->null_ptr, - (int) ((byte*) f->null_ptr - table->record[0]))); + (int) ((uchar*) f->null_ptr - table->record[0]))); if (f->type() == MYSQL_TYPE_BIT) { Field_bit *g= (Field_bit*) f; DBUG_PRINT("MYSQL_TYPE_BIT",("field_length: %d bit_ptr: 0x%lx[+%d] " "bit_ofs: %d bit_len: %u", g->field_length, (long) g->bit_ptr, - (int) ((byte*) g->bit_ptr - + (int) ((uchar*) g->bit_ptr - table->record[0]), g->bit_ofs, g->bit_len)); } @@ -704,7 +704,7 @@ static NDB_SHARE *ndbcluster_check_ndb_apply_status_share() pthread_mutex_lock(&ndbcluster_mutex); void *share= hash_search(&ndbcluster_open_tables, - NDB_APPLY_TABLE_FILE, + (uchar*) NDB_APPLY_TABLE_FILE, sizeof(NDB_APPLY_TABLE_FILE) - 1); DBUG_PRINT("info",("ndbcluster_check_ndb_apply_status_share %s 0x%lx", NDB_APPLY_TABLE_FILE, (long) share)); @@ -722,7 +722,7 @@ static NDB_SHARE *ndbcluster_check_ndb_schema_share() pthread_mutex_lock(&ndbcluster_mutex); void *share= hash_search(&ndbcluster_open_tables, - NDB_SCHEMA_TABLE_FILE, + (uchar*) NDB_SCHEMA_TABLE_FILE, sizeof(NDB_SCHEMA_TABLE_FILE) - 1); DBUG_PRINT("info",("ndbcluster_check_ndb_schema_share %s 0x%lx", NDB_SCHEMA_TABLE_FILE, (long) share)); @@ -928,7 +928,7 @@ static void ndbcluster_get_schema(NDB_SHARE *share, TABLE *table= share->table; Field **field; /* unpack blob values */ - byte* blobs_buffer= 0; + uchar* blobs_buffer= 0; uint blobs_buffer_size= 0; my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); { @@ -943,14 +943,14 @@ static void ndbcluster_get_schema(NDB_SHARE *share, DBUG_ASSERT(FALSE); } } - /* db varchar 1 length byte */ + /* db varchar 1 length uchar */ field= table->field; s->db_length= *(uint8*)(*field)->ptr; DBUG_ASSERT(s->db_length <= (*field)->field_length); DBUG_ASSERT((*field)->field_length + 1 == sizeof(s->db)); memcpy(s->db, (*field)->ptr + 1, s->db_length); s->db[s->db_length]= 0; - /* name varchar 1 length byte */ + /* name varchar 1 length uchar */ field++; s->name_length= *(uint8*)(*field)->ptr; DBUG_ASSERT(s->name_length <= (*field)->field_length); @@ -967,13 +967,11 @@ static void ndbcluster_get_schema(NDB_SHARE *share, { Field_blob *field_blob= (Field_blob*)(*field); uint blob_len= field_blob->get_length((*field)->ptr); - char *blob_ptr= 0; + uchar *blob_ptr= 0; field_blob->get_ptr(&blob_ptr); assert(blob_len == 0 || blob_ptr != 0); s->query_length= blob_len; - s->query= sql_alloc(blob_len+1); - memcpy(s->query, blob_ptr, blob_len); - s->query[blob_len]= 0; + s->query= sql_strmake((char*) blob_ptr, blob_len); } /* node_id */ field++; @@ -1342,7 +1340,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, (void) pthread_mutex_unlock(&ndb_schema_object->mutex); } - DBUG_DUMP("schema_subscribers", (char*)schema_subscribers.bitmap, + DBUG_DUMP("schema_subscribers", (uchar*)schema_subscribers.bitmap, no_bytes_in_map(&schema_subscribers)); DBUG_PRINT("info", ("bitmap_is_clear_all(&schema_subscribers): %d", bitmap_is_clear_all(&schema_subscribers))); @@ -1546,7 +1544,7 @@ end: bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, + (uchar*)ndb_schema_object->slock_bitmap.bitmap, no_bytes_in_map(&ndb_schema_object->slock_bitmap)); if (bitmap_is_clear_all(&ndb_schema_object->slock_bitmap)) @@ -1631,8 +1629,8 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, { const char *tabname= table_share->table_name.str; char key[FN_REFLEN]; - const void *data= 0, *pack_data= 0; - uint length, pack_length; + uchar *data= 0, *pack_data= 0; + size_t length, pack_length; int error; NDBDICT *dict= ndb->getDictionary(); const NDBTAB *altered_table= pOp->getTable(); @@ -1650,7 +1648,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, packfrm(data, length, &pack_data, &pack_length) == 0 && cmp_frm(altered_table, pack_data, pack_length)) { - DBUG_DUMP("frm", (char*)altered_table->getFrmData(), + DBUG_DUMP("frm", (uchar*) altered_table->getFrmData(), altered_table->getFrmLength()); pthread_mutex_lock(&LOCK_open); Ndb_table_guard ndbtab_g(dict, tabname); @@ -1661,7 +1659,8 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); data= NULL; - if ((error= unpackfrm(&data, &length, altered_table->getFrmData())) || + if ((error= unpackfrm(&data, &length, + (const uchar*) altered_table->getFrmData())) || (error= writefrm(key, data, length))) { sql_print_information("NDB: Failed write frm for %s.%s, error %d", @@ -1917,16 +1916,16 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, pthread_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { - DBUG_PRINT("info", ("NDB binlog: Skipping locally defined table '%s.%s'", + DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", schema->db, schema->name)); - sql_print_error("NDB binlog: Skipping locally defined table '%s.%s' from " + sql_print_error("NDB Binlog: Skipping locally defined table '%s.%s' from " "binlog schema event '%s' from node %d. ", schema->db, schema->name, schema->query, schema->node_id); } else if (ndb_create_table_from_engine(thd, schema->db, schema->name)) { - sql_print_error("NDB binlog: Could not discover table '%s.%s' from " + sql_print_error("NDB Binlog: Could not discover table '%s.%s' from " "binlog schema event '%s' from node %d. " "my_errno: %d", schema->db, schema->name, schema->query, @@ -1934,7 +1933,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); MYSQL_ERROR *err; while ((err= it++)) - sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg); + sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg); } pthread_mutex_unlock(&LOCK_open); log_query= 1; @@ -1956,7 +1955,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, else { /* Database contained local tables, leave it */ - sql_print_error("NDB binlog: Skipping drop database '%s' since it contained local tables " + sql_print_error("NDB Binlog: Skipping drop database '%s' since it contained local tables " "binlog schema event '%s' from node %d. ", schema->db, schema->query, schema->node_id); @@ -1985,7 +1984,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, if (log_query && ndb_binlog_running) ndb_binlog_query(thd, schema); /* signal that schema operation has been handled */ - DBUG_DUMP("slock", (char*)schema->slock, schema->slock_length); + DBUG_DUMP("slock", (uchar*) schema->slock, schema->slock_length); if (bitmap_is_set(&slock, node_id)) { if (post_epoch_unlock) @@ -2132,14 +2131,14 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, pthread_mutex_lock(&ndbcluster_mutex); NDB_SCHEMA_OBJECT *ndb_schema_object= (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, - (byte*) key, strlen(key)); + (uchar*) key, strlen(key)); if (ndb_schema_object) { pthread_mutex_lock(&ndb_schema_object->mutex); memcpy(ndb_schema_object->slock, schema->slock, sizeof(ndb_schema_object->slock)); DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, + (uchar*)ndb_schema_object->slock_bitmap.bitmap, no_bytes_in_map(&ndb_schema_object->slock_bitmap)); pthread_mutex_unlock(&ndb_schema_object->mutex); pthread_cond_signal(&injector_cond); @@ -2207,23 +2206,23 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, pthread_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { - DBUG_PRINT("info", ("NDB binlog: Skipping locally defined table '%s.%s'", + DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", schema->db, schema->name)); - sql_print_error("NDB binlog: Skipping locally defined table '%s.%s' from " + sql_print_error("NDB Binlog: Skipping locally defined table '%s.%s' from " "binlog schema event '%s' from node %d. ", schema->db, schema->name, schema->query, schema->node_id); } else if (ndb_create_table_from_engine(thd, schema->db, schema->name)) { - sql_print_error("NDB binlog: Could not discover table '%s.%s' from " + sql_print_error("NDB Binlog: Could not discover table '%s.%s' from " "binlog schema event '%s' from node %d. my_errno: %d", schema->db, schema->name, schema->query, schema->node_id, my_errno); List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); MYSQL_ERROR *err; while ((err= it++)) - sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg); + sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg); } pthread_mutex_unlock(&LOCK_open); } @@ -2523,7 +2522,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, /* Handle any trailing share */ NDB_SHARE *share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables, - (byte*) key, key_len); + (uchar*) key, key_len); if (share && share_may_exist) { @@ -2934,10 +2933,10 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, if (is_ndb_compatible_type(f)) { DBUG_PRINT("info", ("%s compatible", col_name)); - attr0.rec= op->getValue(col_name, f->ptr); + attr0.rec= op->getValue(col_name, (char*) f->ptr); attr1.rec= op->getPreValue(col_name, - (f->ptr - share->table->record[0]) + - share->table->record[1]); + (f->ptr - share->table->record[0]) + + (char*) share->table->record[1]); } else if (! (f->flags & BLOB_FLAG)) { @@ -3323,7 +3322,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp, for now malloc/free blobs buffer each time TODO if possible share single permanent buffer with handlers */ - byte* blobs_buffer[2] = { 0, 0 }; + uchar* blobs_buffer[2] = { 0, 0 }; uint blobs_buffer_size[2] = { 0, 0 }; switch(pOp->getEventType()) @@ -3483,11 +3482,13 @@ private: Injector thread main loop ****************************************************************/ -static byte *ndb_schema_objects_get_key(NDB_SCHEMA_OBJECT *schema_object, uint *length, - my_bool not_used __attribute__((unused))) +static uchar * +ndb_schema_objects_get_key(NDB_SCHEMA_OBJECT *schema_object, + size_t *length, + my_bool not_used __attribute__((unused))) { *length= schema_object->key_length; - return (byte*) schema_object->key; + return (uchar*) schema_object->key; } static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, @@ -3503,7 +3504,7 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, pthread_mutex_lock(&ndbcluster_mutex); while (!(ndb_schema_object= (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, - (byte*) key, + (uchar*) key, length))) { if (!create_if_not_exists) @@ -3521,9 +3522,9 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, ndb_schema_object->key= (char *)(ndb_schema_object+1); memcpy(ndb_schema_object->key, key, length + 1); ndb_schema_object->key_length= length; - if (my_hash_insert(&ndb_schema_objects, (byte*) ndb_schema_object)) + if (my_hash_insert(&ndb_schema_objects, (uchar*) ndb_schema_object)) { - my_free((gptr) ndb_schema_object, 0); + my_free((uchar*) ndb_schema_object, 0); break; } pthread_mutex_init(&ndb_schema_object->mutex, MY_MUTEX_INIT_FAST); @@ -3553,9 +3554,9 @@ static void ndb_free_schema_object(NDB_SCHEMA_OBJECT **ndb_schema_object, if (!--(*ndb_schema_object)->use_count) { DBUG_PRINT("info", ("use_count: %d", (*ndb_schema_object)->use_count)); - hash_delete(&ndb_schema_objects, (byte*) *ndb_schema_object); + hash_delete(&ndb_schema_objects, (uchar*) *ndb_schema_object); pthread_mutex_destroy(&(*ndb_schema_object)->mutex); - my_free((gptr) *ndb_schema_object, MYF(0)); + my_free((uchar*) *ndb_schema_object, MYF(0)); *ndb_schema_object= 0; } else @@ -3673,15 +3674,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) if (opt_bin_log) { - if (global_system_variables.binlog_format == BINLOG_FORMAT_ROW || - global_system_variables.binlog_format == BINLOG_FORMAT_MIXED) - { - ndb_binlog_running= TRUE; - } - else - { - sql_print_error("NDB: only row based binary logging is supported"); - } + ndb_binlog_running= TRUE; } /* Thread start up completed */ @@ -3995,7 +3988,7 @@ restart: NdbDictionary::Event::TE_DELETE)) == 0) { DBUG_PRINT("info", ("skipping non data event table: %.*s", - name.length, name.str)); + (int) name.length, name.str)); continue; } if (!trans.good()) @@ -4004,7 +3997,8 @@ restart: ("Found new data event, initializing transaction")); inj->new_trans(thd, &trans); } - DBUG_PRINT("info", ("use_table: %.*s", name.length, name.str)); + DBUG_PRINT("info", ("use_table: %.*s", + (int) name.length, name.str)); injector::transaction::table tbl(table, TRUE); IF_DBUG(int ret=) trans.use_table(::server_id, tbl); DBUG_ASSERT(ret == 0); @@ -4018,7 +4012,8 @@ restart: #ifndef DBUG_OFF const LEX_STRING& name= table->s->table_name; - DBUG_PRINT("info", ("use_table: %.*s", name.length, name.str)); + DBUG_PRINT("info", ("use_table: %.*s", + (int) name.length, name.str)); #endif injector::transaction::table tbl(table, TRUE); IF_DBUG(int ret=) trans.use_table(::server_id, tbl); @@ -4137,7 +4132,7 @@ restart: injector::transaction::binlog_pos start= trans.start_pos(); if (int r= trans.commit()) { - sql_print_error("NDB binlog: " + sql_print_error("NDB Binlog: " "Error during COMMIT of GCI. Error: %d", r); /* TODO: Further handling? */ diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index ac0d769433e..b5b8d0d9745 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -184,7 +184,7 @@ int ndbcluster_find_all_files(THD *thd); #endif /* HAVE_NDB_BINLOG */ void ndb_unpack_record(TABLE *table, NdbValue *value, - MY_BITMAP *defined, byte *buf); + MY_BITMAP *defined, uchar *buf); char *ndb_pack_varchar(const NDBCOL *col, char *buf, const char *str, int sz); diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index 267be17c330..c686e83504c 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -1377,9 +1377,9 @@ ha_ndbcluster_cond::generate_scan_filter_from_cond(NdbScanFilter& filter) int ha_ndbcluster_cond::generate_scan_filter_from_key(NdbScanOperation *op, const KEY* key_info, - const byte *key, + const uchar *key, uint key_len, - byte *buf) + uchar *buf) { KEY_PART_INFO* key_part= key_info->key_part; KEY_PART_INFO* end= key_part+key_info->key_parts; @@ -1392,9 +1392,9 @@ int ha_ndbcluster_cond::generate_scan_filter_from_key(NdbScanOperation *op, { Field* field= key_part->field; uint32 pack_len= field->pack_length(); - const byte* ptr= key; + const uchar* ptr= key; DBUG_PRINT("info", ("Filtering value for %s", field->field_name)); - DBUG_DUMP("key", (char*)ptr, pack_len); + DBUG_DUMP("key", ptr, pack_len); if (key_part->null_bit) { DBUG_PRINT("info", ("Generating ISNULL filter")); diff --git a/sql/ha_ndbcluster_cond.h b/sql/ha_ndbcluster_cond.h index b6368afe262..4d1d2ef9f92 100644 --- a/sql/ha_ndbcluster_cond.h +++ b/sql/ha_ndbcluster_cond.h @@ -198,7 +198,7 @@ public: return value.item->str_value.ptr(); break; case(NDB_FIELD): - return value.field_value->field->ptr; + return (char*) value.field_value->field->ptr; default: break; } @@ -470,9 +470,9 @@ public: int generate_scan_filter_from_cond(NdbScanFilter& filter); int generate_scan_filter_from_key(NdbScanOperation* op, const KEY* key_info, - const byte *key, + const uchar *key, uint key_len, - byte *buf); + uchar *buf); private: bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond, TABLE *table, const NdbDictionary::Table *ndb_table); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e741ef7deb6..0c4f3cf708f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1224,9 +1224,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, const char *path, ulonglong *copied, ulonglong *deleted, - const void *pack_frm_data + const uchar *pack_frm_data __attribute__((unused)), - uint pack_frm_len + size_t pack_frm_len __attribute__((unused))) { List_iterator<partition_element> part_it(m_part_info->partitions); @@ -1964,8 +1964,8 @@ bool ha_partition::create_handler_file(const char *name) if ((file= my_create(file_name, CREATE_MODE, O_RDWR | O_TRUNC, MYF(MY_WME))) >= 0) { - result= my_write(file, (byte *) file_buffer, tot_len_byte, - MYF(MY_WME | MY_NABP)); + result= my_write(file, (uchar *) file_buffer, tot_len_byte, + MYF(MY_WME | MY_NABP)) != 0; VOID(my_close(file, MYF(0))); } else @@ -2146,14 +2146,14 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) /* Following could be done with my_stat to read in whole file */ if ((file= my_open(buff, O_RDONLY | O_SHARE, MYF(0))) < 0) DBUG_RETURN(TRUE); - if (my_read(file, (byte *) & buff[0], 8, MYF(MY_NABP))) + if (my_read(file, (uchar *) & buff[0], 8, MYF(MY_NABP))) goto err1; len_words= uint4korr(buff); len_bytes= 4 * len_words; - if (!(file_buffer= my_malloc(len_bytes, MYF(0)))) + if (!(file_buffer= (char*) my_malloc(len_bytes, MYF(0)))) goto err1; VOID(my_seek(file, 0, MY_SEEK_SET, MYF(0))); - if (my_read(file, (byte *) file_buffer, len_bytes, MYF(MY_NABP))) + if (my_read(file, (uchar *) file_buffer, len_bytes, MYF(MY_NABP))) goto err2; chksum= 0; @@ -2252,7 +2252,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) alloc_len+= table->s->max_key_length; if (!m_ordered_rec_buffer) { - if (!(m_ordered_rec_buffer= (byte*)my_malloc(alloc_len, MYF(MY_WME)))) + if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME)))) { DBUG_RETURN(1); } @@ -2271,7 +2271,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) int2store(ptr, i); ptr+= m_rec_length + PARTITION_BYTES_IN_POS; } while (++i < m_tot_parts); - m_start_key.key= (const byte*)ptr; + m_start_key.key= (const uchar*)ptr; } } @@ -2657,13 +2657,13 @@ void ha_partition::unlock_row() may be used in determining which partition the row should be written to. */ -int ha_partition::write_row(byte * buf) +int ha_partition::write_row(uchar * buf) { uint32 part_id; int error; longlong func_value; #ifdef NOT_NEEDED - byte *rec0= m_rec0; + uchar *rec0= m_rec0; #endif DBUG_ENTER("ha_partition::write_row"); DBUG_ASSERT(buf == m_rec0); @@ -2737,7 +2737,7 @@ int ha_partition::write_row(byte * buf) old_data is normally record[1] but may be anything */ -int ha_partition::update_row(const byte *old_data, byte *new_data) +int ha_partition::update_row(const uchar *old_data, uchar *new_data) { uint32 new_part_id, old_part_id; int error; @@ -2809,7 +2809,7 @@ int ha_partition::update_row(const byte *old_data, byte *new_data) buf is either record[0] or record[1] */ -int ha_partition::delete_row(const byte *buf) +int ha_partition::delete_row(const uchar *buf) { uint32 part_id; int error; @@ -3080,7 +3080,7 @@ int ha_partition::rnd_end() sql_table.cc, and sql_update.cc. */ -int ha_partition::rnd_next(byte *buf) +int ha_partition::rnd_next(uchar *buf) { handler *file; int result= HA_ERR_END_OF_FILE; @@ -3173,7 +3173,7 @@ end: Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. */ -void ha_partition::position(const byte *record) +void ha_partition::position(const uchar *record) { handler *file= m_file[m_last_part]; DBUG_ENTER("ha_partition::position"); @@ -3213,13 +3213,13 @@ void ha_partition::position(const byte *record) sql_update.cc. */ -int ha_partition::rnd_pos(byte * buf, byte *pos) +int ha_partition::rnd_pos(uchar * buf, uchar *pos) { uint part_id; handler *file; DBUG_ENTER("ha_partition::rnd_pos"); - part_id= uint2korr((const byte *) pos); + part_id= uint2korr((const uchar *) pos); DBUG_ASSERT(part_id < m_tot_parts); file= m_file[part_id]; m_last_part= part_id; @@ -3351,7 +3351,7 @@ int ha_partition::index_end() used in conjuntion with multi read ranges. */ -int ha_partition::index_read(byte * buf, const byte * key, +int ha_partition::index_read(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { @@ -3372,7 +3372,7 @@ int ha_partition::index_read(byte * buf, const byte * key, see index_read for rest */ -int ha_partition::common_index_read(byte *buf, const byte *key, +int ha_partition::common_index_read(uchar *buf, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) { @@ -3449,7 +3449,7 @@ int ha_partition::common_index_read(byte *buf, const byte *key, and sql_select.cc. */ -int ha_partition::index_first(byte * buf) +int ha_partition::index_first(uchar * buf) { DBUG_ENTER("ha_partition::index_first"); @@ -3480,7 +3480,7 @@ int ha_partition::index_first(byte * buf) and sql_select.cc. */ -int ha_partition::index_last(byte * buf) +int ha_partition::index_last(uchar * buf) { DBUG_ENTER("ha_partition::index_last"); @@ -3497,7 +3497,7 @@ int ha_partition::index_last(byte * buf) see index_first for rest */ -int ha_partition::common_first_last(byte *buf) +int ha_partition::common_first_last(uchar *buf) { int error; @@ -3528,7 +3528,7 @@ int ha_partition::common_first_last(byte *buf) Can only be used on indexes supporting HA_READ_ORDER */ -int ha_partition::index_read_last(byte *buf, const byte *key, +int ha_partition::index_read_last(uchar *buf, const uchar *key, key_part_map keypart_map) { DBUG_ENTER("ha_partition::index_read_last"); @@ -3555,7 +3555,7 @@ int ha_partition::index_read_last(byte *buf, const byte *key, Used to read forward through the index. */ -int ha_partition::index_next(byte * buf) +int ha_partition::index_next(uchar * buf) { DBUG_ENTER("ha_partition::index_next"); @@ -3591,7 +3591,7 @@ int ha_partition::index_next(byte * buf) as supplied in the call. */ -int ha_partition::index_next_same(byte *buf, const byte *key, uint keylen) +int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen) { DBUG_ENTER("ha_partition::index_next_same"); @@ -3618,7 +3618,7 @@ int ha_partition::index_next_same(byte *buf, const byte *key, uint keylen) Used to read backwards through the index. */ -int ha_partition::index_prev(byte * buf) +int ha_partition::index_prev(uchar * buf) { DBUG_ENTER("ha_partition::index_prev"); @@ -3727,7 +3727,7 @@ int ha_partition::read_range_next() of them */ -int ha_partition::partition_scan_set_up(byte * buf, bool idx_read_flag) +int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) { DBUG_ENTER("ha_partition::partition_scan_set_up"); @@ -3808,7 +3808,7 @@ int ha_partition::partition_scan_set_up(byte * buf, bool idx_read_flag) perform any sort. */ -int ha_partition::handle_unordered_next(byte *buf, bool is_next_same) +int ha_partition::handle_unordered_next(uchar *buf, bool is_next_same) { handler *file= file= m_file[m_part_spec.start_part]; int error; @@ -3863,7 +3863,7 @@ int ha_partition::handle_unordered_next(byte *buf, bool is_next_same) Both initial start and after completing scan on one partition. */ -int ha_partition::handle_unordered_scan_next_partition(byte * buf) +int ha_partition::handle_unordered_scan_next_partition(uchar * buf) { uint i; DBUG_ENTER("ha_partition::handle_unordered_scan_next_partition"); @@ -3950,7 +3950,7 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf) entries. */ -int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) +int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) { uint i; uint j= 0; @@ -3965,7 +3965,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) { if (!(bitmap_is_set(&(m_part_info->used_partitions), i))) continue; - byte *rec_buf_ptr= rec_buf(i); + uchar *rec_buf_ptr= rec_buf(i); int error; handler *file= m_file[i]; @@ -4000,7 +4000,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) /* Initialise queue without order first, simply insert */ - queue_element(&m_queue, j++)= (byte*)queue_buf(i); + queue_element(&m_queue, j++)= (uchar*)queue_buf(i); } else if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { @@ -4037,11 +4037,11 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) NONE */ -void ha_partition::return_top_record(byte *buf) +void ha_partition::return_top_record(uchar *buf) { uint part_id; - byte *key_buffer= queue_top(&m_queue); - byte *rec_buffer= key_buffer + PARTITION_BYTES_IN_POS; + uchar *key_buffer= queue_top(&m_queue); + uchar *rec_buffer= key_buffer + PARTITION_BYTES_IN_POS; part_id= uint2korr(key_buffer); memcpy(buf, rec_buffer, m_rec_length); @@ -4064,7 +4064,7 @@ void ha_partition::return_top_record(byte *buf) other Error code */ -int ha_partition::handle_ordered_next(byte *buf, bool is_next_same) +int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same) { int error; uint part_id= m_top_entry; @@ -4113,7 +4113,7 @@ int ha_partition::handle_ordered_next(byte *buf, bool is_next_same) other Error code */ -int ha_partition::handle_ordered_prev(byte *buf) +int ha_partition::handle_ordered_prev(uchar *buf) { int error; uint part_id= m_top_entry; @@ -4253,22 +4253,16 @@ int ha_partition::info(uint flag) if (flag & HA_STATUS_AUTO) { - ulonglong nb_reserved_values; + ulonglong auto_increment_value= 0; DBUG_PRINT("info", ("HA_STATUS_AUTO")); - /* we don't want to reserve any values, it's pure information */ - - if (table->found_next_number_field) + file_array= m_file; + do { - /* - Can only call get_auto_increment for tables that actually - have auto_increment columns, otherwise there will be - problems in handlers that don't expect get_auto_increment - for non-autoincrement tables. - */ - get_auto_increment(0, 0, 0, &stats.auto_increment_value, - &nb_reserved_values); - release_auto_increment(); - } + file= *file_array; + file->info(HA_STATUS_AUTO); + set_if_bigger(auto_increment_value, file->stats.auto_increment_value); + } while (*(++file_array)); + stats.auto_increment_value= auto_increment_value; } if (flag & HA_STATUS_VARIABLE) { @@ -5358,7 +5352,7 @@ uint ha_partition::min_record_length(uint options) const they are the same. Sort in partition id order if not equal. */ -int ha_partition::cmp_ref(const byte *ref1, const byte *ref2) +int ha_partition::cmp_ref(const uchar *ref1, const uchar *ref2) { uint part_id; my_ptrdiff_t diff1, diff2; @@ -5567,11 +5561,11 @@ static int partition_init= 0; Function we use in the creation of our hash to get key. */ -static byte *partition_get_key(PARTITION_SHARE *share, uint *length, +static uchar *partition_get_key(PARTITION_SHARE *share, size_t *length, my_bool not_used __attribute__ ((unused))) { *length= share->table_name_length; - return (byte *) share->table_name; + return (uchar *) share->table_name; } /* @@ -5611,12 +5605,12 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) length= (uint) strlen(table_name); if (!(share= (PARTITION_SHARE *) hash_search(&partition_open_tables, - (byte *) table_name, length))) + (uchar *) table_name, length))) { if (!(share= (PARTITION_SHARE *) my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &share, sizeof(*share), - &tmp_name, length + 1, NullS))) + &share, (uint) sizeof(*share), + &tmp_name, (uint) length + 1, NullS))) { pthread_mutex_unlock(&partition_mutex); return NULL; @@ -5626,7 +5620,7 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) share->table_name_length= length; share->table_name= tmp_name; strmov(share->table_name, table_name); - if (my_hash_insert(&partition_open_tables, (byte *) share)) + if (my_hash_insert(&partition_open_tables, (uchar *) share)) goto error; thr_lock_init(&share->lock); pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); @@ -5638,7 +5632,7 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) error: pthread_mutex_unlock(&partition_mutex); - my_free((gptr) share, MYF(0)); + my_free((uchar*) share, MYF(0)); return NULL; } @@ -5655,10 +5649,10 @@ static int free_share(PARTITION_SHARE *share) pthread_mutex_lock(&partition_mutex); if (!--share->use_count) { - hash_delete(&partition_open_tables, (byte *) share); + hash_delete(&partition_open_tables, (uchar *) share); thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->mutex); - my_free((gptr) share, MYF(0)); + my_free((uchar*) share, MYF(0)); } pthread_mutex_unlock(&partition_mutex); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index f5695e91ee0..a168007ea04 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -63,12 +63,12 @@ private: handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors partition_info *m_part_info; // local reference to partition - byte *m_start_key_ref; // Reference of start key in current + uchar *m_start_key_ref; // Reference of start key in current // index scan info Field **m_part_field_array; // Part field array locally to save acc - byte *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan + uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan KEY *m_curr_key_info; // Current index - byte *m_rec0; // table->record[0] + uchar *m_rec0; // table->record[0] QUEUE m_queue; // Prio queue used by sorted read /* Since the partition handler is a handler on top of other handlers, it @@ -199,8 +199,8 @@ public: const char *path, ulonglong *copied, ulonglong *deleted, - const void *pack_frm_data, - uint pack_frm_len); + const uchar *pack_frm_data, + size_t pack_frm_len); virtual int drop_partitions(const char *path); virtual int rename_partitions(const char *path); bool get_no_parts(const char *name, uint *no_parts) @@ -310,9 +310,9 @@ public: number of calls to write_row. Not yet though. */ - virtual int write_row(byte * buf); - virtual int update_row(const byte * old_data, byte * new_data); - virtual int delete_row(const byte * buf); + virtual int write_row(uchar * buf); + virtual int update_row(const uchar * old_data, uchar * new_data); + virtual int delete_row(const uchar * buf); virtual int delete_all_rows(void); virtual void start_bulk_insert(ha_rows rows); virtual int end_bulk_insert(); @@ -351,9 +351,9 @@ public: */ virtual int rnd_init(bool scan); virtual int rnd_end(); - virtual int rnd_next(byte * buf); - virtual int rnd_pos(byte * buf, byte * pos); - virtual void position(const byte * record); + virtual int rnd_next(uchar * buf); + virtual int rnd_pos(uchar * buf, uchar * pos); + virtual void position(const uchar * record); /* ------------------------------------------------------------------------- @@ -387,7 +387,7 @@ public: index_init initializes an index before using it and index_end does any end processing needed. */ - virtual int index_read(byte * buf, const byte * key, + virtual int index_read(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); virtual int index_init(uint idx, bool sorted); @@ -397,12 +397,12 @@ public: These methods are used to jump to next or previous entry in the index scan. There are also methods to jump to first and last entry. */ - virtual int index_next(byte * buf); - virtual int index_prev(byte * buf); - virtual int index_first(byte * buf); - virtual int index_last(byte * buf); - virtual int index_next_same(byte * buf, const byte * key, uint keylen); - virtual int index_read_last(byte * buf, const byte * key, + virtual int index_next(uchar * buf); + virtual int index_prev(uchar * buf); + virtual int index_first(uchar * buf); + virtual int index_last(uchar * buf); + virtual int index_next_same(uchar * buf, const uchar * key, uint keylen); + virtual int index_read_last(uchar * buf, const uchar * key, key_part_map keypart_map); /* @@ -410,7 +410,7 @@ public: handler.cc, no storage engine has implemented it so neither will the partition handler. - virtual int read_first_row(byte *buf, uint primary_key); + virtual int read_first_row(uchar *buf, uint primary_key); */ /* @@ -428,27 +428,27 @@ public: virtual int read_range_next(); private: - int common_index_read(byte * buf, const byte * key, + int common_index_read(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); - int common_first_last(byte * buf); - int partition_scan_set_up(byte * buf, bool idx_read_flag); - int handle_unordered_next(byte * buf, bool next_same); - int handle_unordered_scan_next_partition(byte * buf); - byte *queue_buf(uint part_id) + int common_first_last(uchar * buf); + int partition_scan_set_up(uchar * buf, bool idx_read_flag); + int handle_unordered_next(uchar * buf, bool next_same); + int handle_unordered_scan_next_partition(uchar * buf); + uchar *queue_buf(uint part_id) { return (m_ordered_rec_buffer + (part_id * (m_rec_length + PARTITION_BYTES_IN_POS))); } - byte *rec_buf(uint part_id) + uchar *rec_buf(uint part_id) { return (queue_buf(part_id) + PARTITION_BYTES_IN_POS); } - int handle_ordered_index_scan(byte * buf, bool reverse_order); - int handle_ordered_next(byte * buf, bool next_same); - int handle_ordered_prev(byte * buf); - void return_top_record(byte * buf); + int handle_ordered_index_scan(uchar * buf, bool reverse_order); + int handle_ordered_next(uchar * buf, bool next_same); + int handle_ordered_prev(uchar * buf); + void return_top_record(uchar * buf); void include_partition_fields_in_used_fields(); public: /* @@ -813,7 +813,7 @@ public: to check whether the rest of the reference part is also the same. ------------------------------------------------------------------------- */ - virtual int cmp_ref(const byte * ref1, const byte * ref2); + virtual int cmp_ref(const uchar * ref1, const uchar * ref2); /* ------------------------------------------------------------------------- MODULE auto increment @@ -877,10 +877,10 @@ public: Fulltext stuff not yet. ------------------------------------------------------------------------- virtual int ft_init() { return HA_ERR_WRONG_COMMAND; } - virtual FT_INFO *ft_init_ext(uint flags,uint inx,const byte *key, + virtual FT_INFO *ft_init_ext(uint flags,uint inx,const uchar *key, uint keylen) { return NULL; } - virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; } + virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } */ /* @@ -889,7 +889,7 @@ public: ------------------------------------------------------------------------- The following method is only used by MyISAM when used as temporary tables in a join. - virtual int restart_rnd_next(byte *buf, byte *pos); + virtual int restart_rnd_next(uchar *buf, uchar *pos); */ /* diff --git a/sql/handler.cc b/sql/handler.cc index c7c3918bd2e..b290c5acaa7 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -368,7 +368,7 @@ static int ha_finish_errors(void) /* Allocate a pointer array for the error message strings. */ if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST))) return 1; - my_free((gptr) errmsgs, MYF(0)); + my_free((uchar*) errmsgs, MYF(0)); return 0; } @@ -406,7 +406,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin) } } - my_free((gptr)hton, MYF(0)); + my_free((uchar*)hton, MYF(0)); DBUG_RETURN(0); } @@ -639,7 +639,7 @@ int ha_prepare(THD *thd) for (; *ht; ht++) { int err; - statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status); + status_var_increment(thd->status_var.ha_prepare_count); if ((*ht)->prepare) { if ((err= (*(*ht)->prepare)(*ht, thd, all))) @@ -734,7 +734,7 @@ int ha_commit_trans(THD *thd, bool all) my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); error= 1; } - statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status); + status_var_increment(thd->status_var.ha_prepare_count); } DBUG_EXECUTE_IF("crash_commit_after_prepare", abort();); if (error || (is_real_trans && xid && @@ -781,7 +781,7 @@ int ha_commit_one_phase(THD *thd, bool all) my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_commit_count,&LOCK_status); + status_var_increment(thd->status_var.ha_commit_count); *ht= 0; } trans->nht=0; @@ -837,7 +837,7 @@ int ha_rollback_trans(THD *thd, bool all) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status); + status_var_increment(thd->status_var.ha_rollback_count); *ht= 0; } trans->nht=0; @@ -1053,7 +1053,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, } // recovery mode if (info->commit_list ? - hash_search(info->commit_list, (byte *)&x, sizeof(x)) != 0 : + hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 : tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT) { #ifndef DBUG_OFF @@ -1123,7 +1123,7 @@ int ha_recover(HASH *commit_list) plugin_foreach(NULL, xarecover_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &info); - my_free((gptr)info.list, MYF(0)); + my_free((uchar*)info.list, MYF(0)); if (info.found_foreign_xids) sql_print_warning("Found %d prepared XA transactions", info.found_foreign_xids); @@ -1247,13 +1247,12 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int err; DBUG_ASSERT((*ht)->savepoint_set != 0); - if ((err= (*(*ht)->savepoint_rollback)(*ht, thd, (byte *)(sv+1)+(*ht)->savepoint_offset))) + if ((err= (*(*ht)->savepoint_rollback)(*ht, thd, (uchar *)(sv+1)+(*ht)->savepoint_offset))) { // cannot happen my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_savepoint_rollback_count, - &LOCK_status); + status_var_increment(thd->status_var.ha_savepoint_rollback_count); trans->no_2pc|=(*ht)->prepare == 0; } /* @@ -1268,7 +1267,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status); + status_var_increment(thd->status_var.ha_rollback_count); *ht=0; // keep it conveniently zero-filled } DBUG_RETURN(error); @@ -1296,12 +1295,12 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv) error=1; break; } - if ((err= (*(*ht)->savepoint_set)(*ht, thd, (byte *)(sv+1)+(*ht)->savepoint_offset))) + if ((err= (*(*ht)->savepoint_set)(*ht, thd, (uchar *)(sv+1)+(*ht)->savepoint_offset))) { // cannot happen my_error(ER_GET_ERRNO, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_savepoint_count,&LOCK_status); + status_var_increment(thd->status_var.ha_savepoint_count); } sv->nht=trans->nht; #endif /* USING_TRANSACTIONS */ @@ -1323,7 +1322,7 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) if (!(*ht)->savepoint_release) continue; if ((err= (*(*ht)->savepoint_release)(*ht, thd, - (byte *)(sv+1)+ + (uchar *)(sv+1)+ (*ht)->savepoint_offset))) { // cannot happen my_error(ER_GET_ERRNO, MYF(0), err); @@ -1393,6 +1392,25 @@ bool ha_flush_logs(handlerton *db_type) return FALSE; } +static const char *check_lowercase_names(handler *file, const char *path, + char *tmp_path) +{ + if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED)) + return path; + + /* Ensure that table handler get path in lower case */ + if (tmp_path != path) + strmov(tmp_path, path); + + /* + we only should turn into lowercase database/table part + so start the process after homedirectory + */ + my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len); + return tmp_path; +} + + /** @brief This should return ENOENT if the file doesn't exists. The .frm file will be deleted only if we return 0 or ENOENT @@ -1416,13 +1434,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) DBUG_RETURN(ENOENT); - if (lower_case_table_names == 2 && !(file->ha_table_flags() & HA_FILE_BASED)) - { - /* Ensure that table handler get path in lower case */ - strmov(tmp_path, path); - my_casedn_str(files_charset_info, tmp_path); - path= tmp_path; - } + path= check_lowercase_names(file, path, tmp_path); if ((error= file->delete_table(path)) && generate_warning) { /* @@ -1489,7 +1501,7 @@ handler *handler::clone(MEM_ROOT *mem_root) void handler::ha_statistic_increment(ulong SSV::*offset) const { - statistic_increment(table->in_use->status_var.*offset, &LOCK_status); + status_var_increment(table->in_use->status_var.*offset); } void **handler::ha_data(THD *thd) const @@ -1573,7 +1585,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, table->db_stat|=HA_READ_ONLY; (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL - if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2))) + if (!(ref= (uchar*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2))) { close(); error=HA_ERR_OUT_OF_MEM; @@ -1591,7 +1603,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, This is never called for InnoDB tables, as these table types has the HA_STATS_RECORDS_IS_EXACT set. */ -int handler::read_first_row(byte * buf, uint primary_key) +int handler::read_first_row(uchar * buf, uint primary_key) { register int error; DBUG_ENTER("handler::read_first_row"); @@ -2000,7 +2012,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment, } else { - byte key[MAX_KEY_LENGTH]; + uchar key[MAX_KEY_LENGTH]; key_copy(key, table->record[0], table->key_info + table->s->next_number_index, table->s->next_number_key_offset); @@ -2054,8 +2066,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg) { /* Key is unknown */ str.copy("", 0, system_charset_info); - my_printf_error(ER_DUP_ENTRY_WITH_KEY_NAME, msg, - MYF(0), str.c_ptr(), "*UNKNOWN*"); + my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*"); } else { @@ -2067,7 +2078,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg) str.length(max_length-4); str.append(STRING_WITH_LEN("...")); } - my_printf_error(ER_DUP_ENTRY_WITH_KEY_NAME, msg, + my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), table->key_info[key_nr].name); } } @@ -2359,12 +2370,12 @@ static bool update_frm_version(TABLE *table) int4store(version, MYSQL_VERSION_ID); - if ((result= my_pwrite(file,(byte*) version,4,51L,MYF_RW))) + if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW))) goto err; - for (entry=(TABLE*) hash_first(&open_cache,(byte*) key,key_length, &state); + for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state); entry; - entry= (TABLE*) hash_next(&open_cache,(byte*) key,key_length, &state)) + entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state)) entry->s->mysql_version= MYSQL_VERSION_ID; } err: @@ -2527,7 +2538,7 @@ int ha_enable_transaction(THD *thd, bool on) DBUG_RETURN(error); } -int handler::index_next_same(byte *buf, const byte *key, uint keylen) +int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) { int error; if (!(error=index_next(buf))) @@ -2599,15 +2610,7 @@ int ha_create_table(THD *thd, const char *path, if (update_create_info) update_create_info_from_table(create_info, &table); - name= share.path.str; - if (lower_case_table_names == 2 && - !(table.file->ha_table_flags() & HA_FILE_BASED)) - { - /* Ensure that handler gets name in lower case */ - strmov(name_buff, name); - my_casedn_str(files_charset_info, name_buff); - name= name_buff; - } + name= check_lowercase_names(table.file, share.path.str, name_buff); error= table.file->create(name, &table, create_info); VOID(closefrm(&table, 0)); @@ -2636,8 +2639,8 @@ err: int ha_create_table_from_engine(THD* thd, const char *db, const char *name) { int error; - const void *frmblob; - uint frmlen; + uchar *frmblob; + size_t frmlen; char path[FN_REFLEN]; HA_CREATE_INFO create_info; TABLE table; @@ -2645,7 +2648,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) DBUG_ENTER("ha_create_table_from_engine"); DBUG_PRINT("enter", ("name '%s'.'%s'", db, name)); - bzero((char*) &create_info,sizeof(create_info)); + bzero((uchar*) &create_info,sizeof(create_info)); if ((error= ha_discover(thd, db, name, &frmblob, &frmlen))) { /* Table could not be discovered and thus not created */ @@ -2657,10 +2660,11 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) frmblob and frmlen are set, write the frm to disk */ - (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,"/",db,"/",name,NullS); + (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,FN_ROOTDIR, + db,FN_ROOTDIR,name,NullS); // Save the frm file error= writefrm(path, frmblob, frmlen); - my_free((char*) frmblob, MYF(0)); + my_free(frmblob, MYF(0)); if (error) DBUG_RETURN(2); @@ -2678,12 +2682,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) update_create_info_from_table(&create_info, &table); create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; - if (lower_case_table_names == 2 && - !(table.file->ha_table_flags() & HA_FILE_BASED)) - { - /* Ensure that handler gets name in lower case */ - my_casedn_str(files_charset_info, path); - } + check_lowercase_names(table.file, path, path); error=table.file->create(path,&table,&create_info); VOID(closefrm(&table, 1)); @@ -2802,8 +2801,8 @@ struct st_discover_args { const char *db; const char *name; - const void** frmblob; - uint* frmlen; + uchar **frmblob; + size_t *frmlen; }; static my_bool discover_handlerton(THD *thd, plugin_ref plugin, @@ -2821,7 +2820,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, } int ha_discover(THD *thd, const char *db, const char *name, - const void **frmblob, uint *frmlen) + uchar **frmblob, size_t *frmlen) { int error= -1; // Table does not exist in any handler DBUG_ENTER("ha_discover"); @@ -2836,7 +2835,7 @@ int ha_discover(THD *thd, const char *db, const char *name, error= 0; if (!error) - statistic_increment(thd->status_var.ha_discover_count,&LOCK_status); + status_var_increment(thd->status_var.ha_discover_count); DBUG_RETURN(error); } @@ -3311,7 +3310,7 @@ int handler::compare_key(key_range *range) } -int handler::index_read_idx(byte * buf, uint index, const byte * key, +int handler::index_read_idx(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { @@ -3377,8 +3376,8 @@ TYPELIB *ha_known_exts(void) const char **ext, *old_ext; known_extensions_id= mysys_usage_id; - found_exts.push_back((char*) triggers_file_ext); - found_exts.push_back((char*) trigname_file_ext); + found_exts.push_back((char*) TRG_EXT); + found_exts.push_back((char*) TRN_EXT); plugin_foreach(NULL, exts_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts); @@ -3571,8 +3570,8 @@ namespace template<class RowsEventT> int binlog_log_row(TABLE* table, - const byte *before_record, - const byte *after_record) + const uchar *before_record, + const uchar *after_record) { if (table->file->ha_table_flags() & HA_HAS_OWN_BINLOGGING) return 0; @@ -3621,13 +3620,13 @@ namespace */ template int - binlog_log_row<Write_rows_log_event>(TABLE *, const byte *, const byte *); + binlog_log_row<Write_rows_log_event>(TABLE *, const uchar *, const uchar *); template int - binlog_log_row<Delete_rows_log_event>(TABLE *, const byte *, const byte *); + binlog_log_row<Delete_rows_log_event>(TABLE *, const uchar *, const uchar *); template int - binlog_log_row<Update_rows_log_event>(TABLE *, const byte *, const byte *); + binlog_log_row<Update_rows_log_event>(TABLE *, const uchar *, const uchar *); } @@ -3640,7 +3639,15 @@ int handler::ha_external_lock(THD *thd, int lock_type) taken a table lock), ha_release_auto_increment() was too. */ DBUG_ASSERT(next_insert_id == 0); - DBUG_RETURN(external_lock(thd, lock_type)); + + /* + We cache the table flags if the locking succeeded. Otherwise, we + keep them as they were when they were fetched in ha_open(). + */ + int error= external_lock(thd, lock_type); + if (error == 0) + cached_table_flags= table_flags(); + DBUG_RETURN(error); } @@ -3651,9 +3658,9 @@ int handler::ha_reset() { DBUG_ENTER("ha_reset"); /* Check that we have called all proper deallocation functions */ - DBUG_ASSERT((byte*) table->def_read_set.bitmap + + DBUG_ASSERT((uchar*) table->def_read_set.bitmap + table->s->column_bitmap_size == - (byte*) table->def_write_set.bitmap); + (uchar*) table->def_write_set.bitmap); DBUG_ASSERT(bitmap_is_set_all(&table->s->all_set)); DBUG_ASSERT(table->key_read == 0); /* ensure that ha_index_end / ha_rnd_end has been called */ @@ -3664,7 +3671,7 @@ int handler::ha_reset() } -int handler::ha_write_row(byte *buf) +int handler::ha_write_row(uchar *buf) { int error; if (unlikely(error= write_row(buf))) @@ -3674,7 +3681,7 @@ int handler::ha_write_row(byte *buf) return 0; } -int handler::ha_update_row(const byte *old_data, byte *new_data) +int handler::ha_update_row(const uchar *old_data, uchar *new_data) { int error; @@ -3691,7 +3698,7 @@ int handler::ha_update_row(const byte *old_data, byte *new_data) return 0; } -int handler::ha_delete_row(const byte *buf) +int handler::ha_delete_row(const uchar *buf) { int error; if (unlikely(error= delete_row(buf))) @@ -3814,7 +3821,7 @@ int fl_log_iterator_next(struct handler_iterator *iterator, void fl_log_iterator_destroy(struct handler_iterator *iterator) { - my_free((gptr)iterator->buffer, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*)iterator->buffer, MYF(MY_ALLOW_ZERO_PTR)); } @@ -3827,7 +3834,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator) MY_DIR *dirp; struct fl_buff *buff; char *name_ptr; - byte *ptr; + uchar *ptr; FILEINFO *file; uint32 i; @@ -3838,7 +3845,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator) { return HA_ITERATOR_ERROR; } - if ((ptr= (byte*)my_malloc(ALIGN_SIZE(sizeof(fl_buff)) + + if ((ptr= (uchar*)my_malloc(ALIGN_SIZE(sizeof(fl_buff)) + ((ALIGN_SIZE(sizeof(LEX_STRING)) + sizeof(enum log_status) + + FN_REFLEN) * diff --git a/sql/handler.h b/sql/handler.h index 052c245b801..e80b62c1250 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -117,6 +117,18 @@ #define HA_HAS_RECORDS (LL(1) << 32) /* records() gives exact count*/ /* Has it's own method of binlog logging */ #define HA_HAS_OWN_BINLOGGING (LL(1) << 33) +/* + Engine is capable of row-format and statement-format logging, + respectively +*/ +#define HA_BINLOG_ROW_CAPABLE (LL(1) << 34) +#define HA_BINLOG_STMT_CAPABLE (LL(1) << 35) + +/* + Set of all binlog flags. Currently only contain the capabilities + flags. + */ +#define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE) /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ @@ -223,6 +235,7 @@ #define HA_LEX_CREATE_TMP_TABLE 1 #define HA_LEX_CREATE_IF_NOT_EXISTS 2 +#define HA_LEX_CREATE_TABLE_LIKE 4 #define HA_OPTION_NO_CHECKSUM (1L << 17) #define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18) #define HA_MAX_REC_LENGTH 65535 @@ -378,9 +391,9 @@ struct xid_t { return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+ gtrid_length+bqual_length; } - byte *key() + uchar *key() { - return (byte *)>rid_length; + return (uchar *)>rid_length; } uint key_length() { @@ -674,8 +687,8 @@ struct handlerton struct handler_iterator *fill_this_in); int (*discover)(handlerton *hton, THD* thd, const char *db, const char *name, - const void** frmblob, - uint* frmlen); + uchar **frmblob, + size_t *frmlen); int (*find_files)(handlerton *hton, THD *thd, const char *db, const char *path, @@ -687,7 +700,7 @@ struct handlerton }; -/* Possible flags of a handlerton */ +/* Possible flags of a handlerton (there can be 32 of them) */ #define HTON_NO_FLAGS 0 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0) #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter @@ -792,19 +805,37 @@ typedef struct st_key_create_information class TABLEOP_HOOKS { public: + TABLEOP_HOOKS() {} + virtual ~TABLEOP_HOOKS() {} + inline void prelock(TABLE **tables, uint count) { do_prelock(tables, count); } - virtual ~TABLEOP_HOOKS() {} - TABLEOP_HOOKS() {} + inline int postlock(TABLE **tables, uint count) + { + return do_postlock(tables, count); + } private: /* Function primitive that is called prior to locking tables */ virtual void do_prelock(TABLE **tables, uint count) { /* Default is to do nothing */ } + + /** + Primitive called after tables are locked. + + If an error is returned, the tables will be unlocked and error + handling start. + + @return Error code or zero. + */ + virtual int do_postlock(TABLE **tables, uint count) + { + return 0; /* Default is to do nothing */ + } }; typedef struct st_savepoint SAVEPOINT; @@ -835,9 +866,9 @@ typedef struct st_ha_check_opt typedef struct st_handler_buffer { - const byte *buffer; /* Buffer one can start using */ - const byte *buffer_end; /* End of buffer */ - byte *end_of_used_area; /* End of area that was used by handler */ + const uchar *buffer; /* Buffer one can start using */ + const uchar *buffer_end; /* End of buffer */ + uchar *end_of_used_area; /* End of area that was used by handler */ } HANDLER_BUFFER; typedef struct system_status_var SSV; @@ -851,7 +882,15 @@ public: ulonglong max_index_file_length; ulonglong delete_length; /* Free bytes */ ulonglong auto_increment_value; - ha_rows records; /* Estimated records in table */ + /* + The number of records in the table. + 0 - means the table has exactly 0 rows + other - if (table_flags() & HA_STATS_RECORDS_IS_EXACT) + the value is the exact number of records in the table + else + it is an estimate + */ + ha_rows records; ha_rows deleted; /* Deleted records */ ulong mean_rec_length; /* physical reclength */ time_t create_time; /* When table was created */ @@ -867,7 +906,7 @@ public: {} }; -uint calculate_key_len(TABLE *, uint, const byte *, key_part_map); +uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map); /* bitmap with first N+1 bits set (keypart_map for a key prefix of [0..N] keyparts) @@ -891,10 +930,13 @@ class handler :public Sql_alloc friend int ha_delete_table(THD*,handlerton*,const char*,const char*, const char*,bool); +public: + typedef ulonglong Table_flags; + protected: struct st_table_share *table_share; /* The table definition */ struct st_table *table; /* The current open table */ - ulonglong cached_table_flags; /* Set on init() and open() */ + Table_flags cached_table_flags; /* Set on init() and open() */ virtual int index_init(uint idx, bool sorted) { active_index=idx; return 0; } virtual int index_end() { active_index=MAX_KEY; return 0; } @@ -907,7 +949,7 @@ class handler :public Sql_alloc */ virtual int rnd_init(bool scan) =0; virtual int rnd_end() { return 0; } - virtual ulonglong table_flags(void) const =0; + virtual Table_flags table_flags(void) const =0; void ha_statistic_increment(ulong SSV::*offset) const; void **ha_data(THD *) const; @@ -918,8 +960,8 @@ class handler :public Sql_alloc virtual int end_bulk_insert() {return 0; } public: handlerton *ht; /* storage engine of this handler */ - byte *ref; /* Pointer to current row */ - byte *dup_ref; /* Pointer to duplicate row */ + uchar *ref; /* Pointer to current row */ + uchar *dup_ref; /* Pointer to duplicate row */ ha_statistics stats; @@ -1121,7 +1163,7 @@ public: { return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0; } - longlong ha_table_flags() { return cached_table_flags; } + Table_flags ha_table_flags() const { return cached_table_flags; } /* Signal that the table->read_set and table->write_set table maps changed @@ -1142,9 +1184,9 @@ public: and delete_row() below. */ int ha_external_lock(THD *thd, int lock_type); - int ha_write_row(byte * buf); - int ha_update_row(const byte * old_data, byte * new_data); - int ha_delete_row(const byte * buf); + int ha_write_row(uchar * buf); + int ha_update_row(const uchar * old_data, uchar * new_data); + int ha_delete_row(const uchar * buf); /* SYNOPSIS @@ -1177,7 +1219,7 @@ public: 0 Bulk delete used by handler 1 Bulk delete not used, normal operation used */ - virtual int bulk_update_row(const byte *old_data, byte *new_data, + virtual int bulk_update_row(const uchar *old_data, uchar *new_data, uint *dup_key_found) { DBUG_ASSERT(FALSE); @@ -1226,7 +1268,7 @@ public: return HA_ERR_WRONG_COMMAND; } private: - virtual int index_read(byte * buf, const byte * key, uint key_len, + virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } public: @@ -1236,7 +1278,7 @@ public: row if available. If the key value is null, begin at the first key of the index. */ - virtual int index_read(byte * buf, const byte * key, key_part_map keypart_map, + virtual int index_read(uchar * buf, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); @@ -1248,20 +1290,20 @@ public: row if available. If the key value is null, begin at the first key of the index. */ - virtual int index_read_idx(byte * buf, uint index, const byte * key, + virtual int index_read_idx(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag); - virtual int index_next(byte * buf) + virtual int index_next(uchar * buf) { return HA_ERR_WRONG_COMMAND; } - virtual int index_prev(byte * buf) + virtual int index_prev(uchar * buf) { return HA_ERR_WRONG_COMMAND; } - virtual int index_first(byte * buf) + virtual int index_first(uchar * buf) { return HA_ERR_WRONG_COMMAND; } - virtual int index_last(byte * buf) + virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } - virtual int index_next_same(byte *buf, const byte *key, uint keylen); + virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); private: - virtual int index_read_last(byte * buf, const byte * key, uint key_len) + virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) { return (my_errno=HA_ERR_WRONG_COMMAND); } public: /** @@ -1269,7 +1311,7 @@ public: The following functions works like index_read, but it find the last row with the current key value or prefix. */ - virtual int index_read_last(byte * buf, const byte * key, + virtual int index_read_last(uchar * buf, const uchar * key, key_part_map keypart_map) { uint key_len= calculate_key_len(table, active_index, key, keypart_map); @@ -1288,21 +1330,21 @@ public: void ft_end() { ft_handler=NULL; } virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } - virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; } - virtual int rnd_next(byte *buf)=0; - virtual int rnd_pos(byte * buf, byte *pos)=0; - virtual int read_first_row(byte *buf, uint primary_key); + virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } + virtual int rnd_next(uchar *buf)=0; + virtual int rnd_pos(uchar * buf, uchar *pos)=0; + virtual int read_first_row(uchar *buf, uint primary_key); /* The following function is only needed for tables that may be temporary tables during joins */ - virtual int restart_rnd_next(byte *buf, byte *pos) + virtual int restart_rnd_next(uchar *buf, uchar *pos) { return HA_ERR_WRONG_COMMAND; } - virtual int rnd_same(byte *buf, uint inx) + virtual int rnd_same(uchar *buf, uint inx) { return HA_ERR_WRONG_COMMAND; } virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key) { return (ha_rows) 10; } - virtual void position(const byte *record)=0; + virtual void position(const uchar *record)=0; virtual int info(uint)=0; // see my_base.h for full description virtual void get_dynamic_partition_info(PARTITION_INFO *stat_info, uint part_id); @@ -1558,8 +1600,8 @@ public: const char *path, ulonglong *copied, ulonglong *deleted, - const void *pack_frm_data, - uint pack_frm_len) + const uchar *pack_frm_data, + size_t pack_frm_len) { return HA_ERR_WRONG_COMMAND; } virtual int drop_partitions(const char *path) { return HA_ERR_WRONG_COMMAND; } @@ -1602,7 +1644,7 @@ public: false otherwise */ virtual bool primary_key_is_clustered() { return FALSE; } - virtual int cmp_ref(const byte *ref1, const byte *ref2) + virtual int cmp_ref(const uchar *ref1, const uchar *ref2) { return memcmp(ref1, ref2, ref_length); } @@ -1647,18 +1689,18 @@ public: { return COMPATIBLE_DATA_NO; } /* These are only called from sql_select for internal temporary tables */ - virtual int write_row(byte *buf __attribute__((unused))) + virtual int write_row(uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } - virtual int update_row(const byte *old_data __attribute__((unused)), - byte *new_data __attribute__((unused))) + virtual int update_row(const uchar *old_data __attribute__((unused)), + uchar *new_data __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } - virtual int delete_row(const byte *buf __attribute__((unused))) + virtual int delete_row(const uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } @@ -1685,6 +1727,8 @@ private: /* Some extern variables used with handlers */ extern const char *ha_row_type[]; +extern const char *tx_isolation_names[]; +extern const char *binlog_format_names[]; extern TYPELIB tx_isolation_typelib; extern TYPELIB myisam_stats_method_typelib; extern ulong total_ha, total_ha_2pc; @@ -1751,7 +1795,7 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat); /* discovery */ int ha_create_table_from_engine(THD* thd, const char *db, const char *name); int ha_discover(THD* thd, const char* dbname, const char* name, - const void** frmblob, uint* frmlen); + uchar** frmblob, size_t* frmlen); int ha_find_files(THD *thd,const char *db,const char *path, const char *wild, bool dir,List<char>* files); int ha_table_exists_in_engine(THD* thd, const char* db, const char* name); diff --git a/sql/hash_filo.h b/sql/hash_filo.h index c25af67b572..ab13d338695 100644 --- a/sql/hash_filo.h +++ b/sql/hash_filo.h @@ -84,10 +84,10 @@ public: first_link=last_link=0; } - hash_filo_element *search(gptr key,uint length) + hash_filo_element *search(uchar* key, size_t length) { hash_filo_element *entry=(hash_filo_element*) - hash_search(&cache,(byte*) key,length); + hash_search(&cache,(uchar*) key,length); if (entry) { // Found; link it first if (entry != first_link) @@ -113,9 +113,9 @@ public: { hash_filo_element *tmp=last_link; last_link=last_link->prev_used; - hash_delete(&cache,(byte*) tmp); + hash_delete(&cache,(uchar*) tmp); } - if (my_hash_insert(&cache,(byte*) entry)) + if (my_hash_insert(&cache,(uchar*) entry)) { if (free_element) (*free_element)(entry); // This should never happen diff --git a/sql/hostname.cc b/sql/hostname.cc index 049220c6b6f..34384a9c8c0 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -84,7 +84,7 @@ static void add_hostname(struct in_addr *in,const char *name) { VOID(pthread_mutex_lock(&hostname_cache->lock)); host_entry *entry; - if (!(entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0))) + if (!(entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) { uint length=name ? (uint) strlen(name) : 0; @@ -115,7 +115,7 @@ void inc_host_errors(struct in_addr *in) { VOID(pthread_mutex_lock(&hostname_cache->lock)); host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0))) + if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) entry->errors++; VOID(pthread_mutex_unlock(&hostname_cache->lock)); } @@ -124,7 +124,7 @@ void reset_host_errors(struct in_addr *in) { VOID(pthread_mutex_lock(&hostname_cache->lock)); host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0))) + if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) entry->errors=0; VOID(pthread_mutex_unlock(&hostname_cache->lock)); } @@ -134,7 +134,7 @@ void reset_host_errors(struct in_addr *in) #define INADDR_LOOPBACK 0x7f000001UL #endif -my_string ip_to_hostname(struct in_addr *in, uint *errors) +char * ip_to_hostname(struct in_addr *in, uint *errors) { uint i; host_entry *entry; @@ -149,7 +149,7 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) if (!(specialflag & SPECIAL_NO_HOST_CACHE)) { VOID(pthread_mutex_lock(&hostname_cache->lock)); - if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0))) + if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) { char *name; if (!entry->hostname) diff --git a/sql/init.cc b/sql/init.cc index ff236c03204..73feaa797c3 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -21,8 +21,6 @@ void unireg_init(ulong options) { - uint i; - double nr; DBUG_ENTER("unireg_init"); MYSYS_PROGRAM_DONT_USE_CURSES(); @@ -40,16 +38,5 @@ void unireg_init(ulong options) VOID(strmov(reg_ext,".frm")); reg_ext_length= 4; specialflag=SPECIAL_SAME_DB_NAME | options; /* Set options from argv */ - /* Make a tab of powers of 10 */ - for (i=0,nr=1.0; i < array_elements(log_10) ; i++) - { /* It's used by filesort... */ - log_10[i]= nr ; nr*= 10.0; - } - /* Make a tab of powers of 0.1 */ - for (i= 0, nr= 0.1; i < array_elements(log_01); i++) - { - log_01[i]= nr; - nr*= 0.1; - } DBUG_VOID_RETURN; } diff --git a/sql/item.cc b/sql/item.cc index 24958f64f2a..4638a1d044d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -161,6 +161,7 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const void item_init(void) { item_user_lock_init(); + uuid_short_init(); } @@ -431,7 +432,7 @@ void Item::cleanup() arg - a dummy parameter, is not used here */ -bool Item::cleanup_processor(byte *arg) +bool Item::cleanup_processor(uchar *arg) { if (fixed) cleanup(); @@ -494,7 +495,7 @@ void Item::rename(char *new_name) pointer to newly allocated item is returned. */ -Item* Item::transform(Item_transformer transformer, byte *arg) +Item* Item::transform(Item_transformer transformer, uchar *arg) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); @@ -552,7 +553,7 @@ void Item_ident::cleanup() DBUG_VOID_RETURN; } -bool Item_ident::remove_dependence_processor(byte * arg) +bool Item_ident::remove_dependence_processor(uchar * arg) { DBUG_ENTER("Item_ident::remove_dependence_processor"); if (depended_from == (st_select_lex *) arg) @@ -583,7 +584,7 @@ bool Item_ident::remove_dependence_processor(byte * arg) for the subsequent items. */ -bool Item_field::collect_item_field_processor(byte *arg) +bool Item_field::collect_item_field_processor(uchar *arg) { DBUG_ENTER("Item_field::collect_item_field_processor"); DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname")); @@ -618,7 +619,7 @@ bool Item_field::collect_item_field_processor(byte *arg) FALSE otherwise */ -bool Item_field::find_item_in_field_list_processor(byte *arg) +bool Item_field::find_item_in_field_list_processor(uchar *arg) { KEY_PART_INFO *first_non_group_part= *((KEY_PART_INFO **) arg); KEY_PART_INFO *last_part= *(((KEY_PART_INFO **) arg) + 1); @@ -641,7 +642,7 @@ bool Item_field::find_item_in_field_list_processor(byte *arg) column read set or to register used fields in a view */ -bool Item_field::register_field_in_read_map(byte *arg) +bool Item_field::register_field_in_read_map(uchar *arg) { TABLE *table= (TABLE *) arg; if (field->table == table || !table) @@ -690,7 +691,7 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) } if (!my_charset_same(cs, system_charset_info)) { - uint32 res_length; + size_t res_length; name= sql_strmake_with_convert(str, name_length= length, cs, MAX_ALIAS_NAME, system_charset_info, &res_length); @@ -785,7 +786,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) */ return NULL; } - if (!(ptr= current_thd->memdup(cstr.ptr(), cstr.length() + 1 ))) + if (!(ptr= current_thd->strmake(cstr.ptr(), cstr.length()))) return NULL; conv->str_value.set(ptr, cstr.length(), cstr.charset()); /* Ensure that no one is going to change the result string */ @@ -2139,7 +2140,7 @@ Item_decimal::Item_decimal(my_decimal *value_par) } -Item_decimal::Item_decimal(const char *bin, int precision, int scale) +Item_decimal::Item_decimal(const uchar *bin, int precision, int scale) { binary2my_decimal(E_DEC_FATAL_ERROR, bin, &decimal_value, precision, scale); @@ -2348,6 +2349,7 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : + strict_type(FALSE), state(NO_VALUE), item_result_type(STRING_RESULT), /* Don't pretend to be a literal unless value for this item is set. */ @@ -2542,16 +2544,16 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) if (entry && entry->value) { item_result_type= entry->type; - switch (entry->type) { + if (strict_type && required_result_type != item_result_type) + DBUG_RETURN(1); + switch (item_result_type) { case REAL_RESULT: set_double(*(double*)entry->value); item_type= Item::REAL_ITEM; - item_result_type= REAL_RESULT; break; case INT_RESULT: set_int(*(longlong*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS); item_type= Item::INT_ITEM; - item_result_type= INT_RESULT; break; case STRING_RESULT: { @@ -2574,7 +2576,6 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) charset of connection, so we have to set it later. */ item_type= Item::STRING_ITEM; - item_result_type= STRING_RESULT; if (set_str((const char *)entry->value, entry->length)) DBUG_RETURN(1); @@ -2588,6 +2589,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) decimals= ent_value->frac; max_length= my_decimal_precision_to_length(ent_value->precision(), decimals, unsigned_flag); + item_type= Item::DECIMAL_ITEM; break; } default: @@ -4067,7 +4069,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) FALSE otherwise */ -bool Item_field::subst_argument_checker(byte **arg) +bool Item_field::subst_argument_checker(uchar **arg) { return (result_type() != STRING_RESULT) || (*arg); } @@ -4099,7 +4101,7 @@ bool Item_field::subst_argument_checker(byte **arg) pointer to the field item, otherwise. */ -Item *Item_field::equal_fields_propagator(byte *arg) +Item *Item_field::equal_fields_propagator(uchar *arg) { if (no_const_subst) return this; @@ -4130,7 +4132,7 @@ Item *Item_field::equal_fields_propagator(byte *arg) See comments in Arg_comparator::set_compare_func() for details */ -bool Item_field::set_no_const_sub(byte *arg) +bool Item_field::set_no_const_sub(uchar *arg) { if (field->charset() != &my_charset_bin) no_const_subst=1; @@ -4165,7 +4167,7 @@ bool Item_field::set_no_const_sub(byte *arg) this - otherwise. */ -Item *Item_field::replace_equal_field(byte *arg) +Item *Item_field::replace_equal_field(uchar *arg) { if (item_equal) { @@ -4315,42 +4317,42 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= new Field_new_decimal((char*) 0, max_length, null_ptr, 0, + field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, decimals, 0, unsigned_flag); break; case MYSQL_TYPE_TINY: - field= new Field_tiny((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, 0, unsigned_flag); break; case MYSQL_TYPE_SHORT: - field= new Field_short((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_short((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, 0, unsigned_flag); break; case MYSQL_TYPE_LONG: - field= new Field_long((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_long((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, 0, unsigned_flag); break; #ifdef HAVE_LONG_LONG case MYSQL_TYPE_LONGLONG: - field= new Field_longlong((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_longlong((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, 0, unsigned_flag); break; #endif case MYSQL_TYPE_FLOAT: - field= new Field_float((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_float((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, decimals, 0, unsigned_flag); break; case MYSQL_TYPE_DOUBLE: - field= new Field_double((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_double((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, decimals, 0, unsigned_flag); break; case MYSQL_TYPE_NULL: - field= new Field_null((char*) 0, max_length, Field::NONE, + field= new Field_null((uchar*) 0, max_length, Field::NONE, name, &my_charset_bin); break; case MYSQL_TYPE_INT24: - field= new Field_medium((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_medium((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name, 0, unsigned_flag); break; case MYSQL_TYPE_NEWDATE: @@ -4367,7 +4369,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) field= new Field_datetime(maybe_null, name, &my_charset_bin); break; case MYSQL_TYPE_YEAR: - field= new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE, + field= new Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name); break; case MYSQL_TYPE_BIT: @@ -4402,9 +4404,11 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) field= new Field_blob(max_length, maybe_null, name, collation.collation); break; // Blob handled outside of case case MYSQL_TYPE_GEOMETRY: - return new Field_geom(max_length, maybe_null, name, table->s, + field= new Field_geom(max_length, maybe_null, name, table->s, (Field::geometry_type) - ((Item_geometry_func *)this)->get_geometry_type()); + ((type() == Item::TYPE_HOLDER) ? + ((Item_type_holder *)this)->get_geometry_type() : + ((Item_geometry_func *)this)->get_geometry_type())); } if (field) field->init(table); @@ -5031,7 +5035,7 @@ void Item_field::update_null_value() this field otherwise */ -Item *Item_field::update_value_transformer(byte *select_arg) +Item *Item_field::update_value_transformer(uchar *select_arg) { SELECT_LEX *select= (SELECT_LEX*)select_arg; DBUG_ASSERT(fixed); @@ -5848,7 +5852,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) same time it can replace some nodes in the tree */ -Item *Item_default_value::transform(Item_transformer transformer, byte *args) +Item *Item_default_value::transform(Item_transformer transformer, uchar *args) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); @@ -6513,6 +6517,10 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) if (Field::result_merge_type(fld_type) == INT_RESULT) decimals= 0; prev_decimal_int_part= item->decimal_int_part(); + if (item->field_type() == MYSQL_TYPE_GEOMETRY) + geometry_type= (item->type() == Item::FIELD_ITEM) ? + ((Item_field *)item)->get_geometry_type() : + (Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type(); } @@ -6790,7 +6798,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table) switch (fld_type) { case MYSQL_TYPE_ENUM: DBUG_ASSERT(enum_set_typelib); - field= new Field_enum((char *) 0, max_length, null_ptr, 0, + field= new Field_enum((uchar *) 0, max_length, null_ptr, 0, Field::NONE, name, get_enum_pack_length(enum_set_typelib->count), enum_set_typelib, collation.collation); @@ -6799,7 +6807,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table) return field; case MYSQL_TYPE_SET: DBUG_ASSERT(enum_set_typelib); - field= new Field_set((char *) 0, max_length, null_ptr, 0, + field= new Field_set((uchar *) 0, max_length, null_ptr, 0, Field::NONE, name, get_set_pack_length(enum_set_typelib->count), enum_set_typelib, collation.collation); diff --git a/sql/item.h b/sql/item.h index 957edbb8f0d..c79107e04bd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -426,7 +426,7 @@ public: }; -typedef bool (Item::*Item_processor) (byte *arg); +typedef bool (Item::*Item_processor) (uchar *arg); /* Analyzer function SYNOPSIS @@ -438,8 +438,8 @@ typedef bool (Item::*Item_processor) (byte *arg); FALSE Don't do it */ -typedef bool (Item::*Item_analyzer) (byte **argp); -typedef Item* (Item::*Item_transformer) (byte *arg); +typedef bool (Item::*Item_analyzer) (uchar **argp); +typedef Item* (Item::*Item_transformer) (uchar *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -448,9 +448,9 @@ class Item { void operator=(Item &); public: static void *operator new(size_t size) - { return (void*) sql_alloc((uint) size); } + { return sql_alloc(size); } static void *operator new(size_t size, MEM_ROOT *mem_root) - { return (void*) alloc_root(mem_root, (uint) size); } + { return alloc_root(mem_root, size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} @@ -476,9 +476,9 @@ public: save_in_field */ String str_value; - my_string name; /* Name from select */ + char * name; /* Name from select */ /* Original item name (if it was renamed)*/ - my_string orig_name; + char * orig_name; Item *next; uint32 max_length; uint name_length; /* Length of name */ @@ -779,12 +779,12 @@ public: static CHARSET_INFO *default_charset(); virtual CHARSET_INFO *compare_collation() { return NULL; } - virtual bool walk(Item_processor processor, bool walk_subquery, byte *arg) + virtual bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (this->*processor)(arg); } - virtual Item* transform(Item_transformer transformer, byte *arg); + virtual Item* transform(Item_transformer transformer, uchar *arg); /* This function performs a generic "compilation" of the Item tree. @@ -802,8 +802,8 @@ public: i.e. analysis is performed top-down while transformation is done bottom-up. */ - virtual Item* compile(Item_analyzer analyzer, byte **arg_p, - Item_transformer transformer, byte *arg_t) + virtual Item* compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t) { if ((this->*analyzer) (arg_p)) return ((this->*transformer) (arg_t)); @@ -816,15 +816,15 @@ public: (*traverser)(this, arg); } - virtual bool remove_dependence_processor(byte * arg) { return 0; } - virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } - virtual bool cleanup_processor(byte *arg); - virtual bool collect_item_field_processor(byte * arg) { return 0; } - virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } - virtual bool change_context_processor(byte *context) { return 0; } - virtual bool reset_query_id_processor(byte *query_id_arg) { return 0; } - virtual bool is_expensive_processor(byte *arg) { return 0; } - virtual bool register_field_in_read_map(byte *arg) { return 0; } + virtual bool remove_dependence_processor(uchar * arg) { return 0; } + virtual bool remove_fixed(uchar * arg) { fixed= 0; return 0; } + virtual bool cleanup_processor(uchar *arg); + virtual bool collect_item_field_processor(uchar * arg) { return 0; } + virtual bool find_item_in_field_list_processor(uchar *arg) { return 0; } + virtual bool change_context_processor(uchar *context) { return 0; } + virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } + virtual bool is_expensive_processor(uchar *arg) { return 0; } + virtual bool register_field_in_read_map(uchar *arg) { return 0; } /* Check if a partition function is allowed SYNOPSIS @@ -877,17 +877,17 @@ public: assumes that there are no multi-byte collations amongst the partition fields. */ - virtual bool check_partition_func_processor(byte *bool_arg) { return TRUE;} - virtual bool subst_argument_checker(byte **arg) + virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;} + virtual bool subst_argument_checker(uchar **arg) { if (*arg) *arg= NULL; return TRUE; } - virtual Item *equal_fields_propagator(byte * arg) { return this; } - virtual bool set_no_const_sub(byte *arg) { return FALSE; } - virtual Item *replace_equal_field(byte * arg) { return this; } + virtual Item *equal_fields_propagator(uchar * arg) { return this; } + virtual bool set_no_const_sub(uchar *arg) { return FALSE; } + virtual Item *replace_equal_field(uchar * arg) { return this; } /* For SP local variable returns pointer to Item representing its @@ -916,7 +916,7 @@ public: virtual Item_field *filed_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } - virtual Item *update_value_transformer(byte *select_arg) { return this; } + virtual Item *update_value_transformer(uchar *select_arg) { return this; } virtual Item *safe_charset_converter(CHARSET_INFO *tocs); void delete_self() { @@ -1224,7 +1224,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(uchar *int_arg) { return FALSE;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1268,9 +1268,9 @@ public: Item_ident(THD *thd, Item_ident *item); const char *full_name() const; void cleanup(); - bool remove_dependence_processor(byte * arg); + bool remove_dependence_processor(uchar * arg); void print(String *str); - virtual bool change_context_processor(byte *cntx) + virtual bool change_context_processor(uchar *cntx) { context= (Name_resolution_context *)cntx; return FALSE; } friend bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, @@ -1379,26 +1379,31 @@ public: bool is_null() { return field->is_null(); } void update_null_value(); Item *get_tmp_table_item(THD *thd); - bool collect_item_field_processor(byte * arg); - bool find_item_in_field_list_processor(byte *arg); - bool register_field_in_read_map(byte *arg); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool collect_item_field_processor(uchar * arg); + bool find_item_in_field_list_processor(uchar *arg); + bool register_field_in_read_map(uchar *arg); + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} void cleanup(); bool result_as_longlong() { return field->can_be_compared_as_longlong(); } Item_equal *find_item_equal(COND_EQUAL *cond_equal); - bool subst_argument_checker(byte **arg); - Item *equal_fields_propagator(byte *arg); - bool set_no_const_sub(byte *arg); - Item *replace_equal_field(byte *arg); + bool subst_argument_checker(uchar **arg); + Item *equal_fields_propagator(uchar *arg); + bool set_no_const_sub(uchar *arg); + Item *replace_equal_field(uchar *arg); inline uint32 max_disp_length() { return field->max_display_length(); } Item_field *filed_for_view_update() { return this; } Item *safe_charset_converter(CHARSET_INFO *tocs); int fix_outer_field(THD *thd, Field **field, Item **reference); - virtual Item *update_value_transformer(byte *select_arg); + virtual Item *update_value_transformer(uchar *select_arg); void print(String *str); + Field::geometry_type get_geometry_type() + { + DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY); + return field->get_geometry_type(); + } friend class Item_default_value; friend class Item_insert_value; friend class st_select_lex_unit; @@ -1433,7 +1438,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_null_result :public Item_null @@ -1446,7 +1451,7 @@ public: { save_in_field(result_field, no_conversions); } - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1456,8 +1461,10 @@ class Item_param :public Item char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; Item *cnvitem; -public: + bool strict_type; + enum Item_result required_result_type; +public: enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, @@ -1585,6 +1592,11 @@ public: Otherwise return FALSE. */ bool eq(const Item *item, bool binary_cmp) const; + void set_strict_type(enum Item_result result_type_arg) + { + strict_type= TRUE; + required_result_type= result_type_arg; + } }; @@ -1653,7 +1665,7 @@ public: Item_decimal(my_decimal *value_par); Item_decimal(longlong val, bool unsig); Item_decimal(double val, int precision, int scale); - Item_decimal(const char *bin, int precision, int scale); + Item_decimal(const uchar *bin, int precision, int scale); enum Type type() const { return DECIMAL_ITEM; } enum Item_result result_type () const { return DECIMAL_RESULT; } @@ -1740,7 +1752,7 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1756,7 +1768,7 @@ public: We have to have a different max_length than 'length' here to ensure that we get the right length if we do use the item to create a new table. In this case max_length must be the maximum - number of chars for a string of this type because we in create_field:: + number of chars for a string of this type because we in Create_field:: divide the max_length with mbmaxlen). */ max_length= str_value.numchars()*cs->mbmaxlen; @@ -1822,7 +1834,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -1837,7 +1849,7 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1849,7 +1861,7 @@ public: CHARSET_INFO *cs= NULL): Item_string(name, length, cs) {} - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1897,7 +1909,7 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1924,7 +1936,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -2044,7 +2056,7 @@ public: { return ref ? (*ref)->real_item() : this; } - bool walk(Item_processor processor, bool walk_subquery, byte *arg) + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (*ref)->walk(processor, walk_subquery, arg); } void print(String *str); bool result_as_longlong() @@ -2223,7 +2235,7 @@ public: } Item *clone_item(); virtual Item *real_item() { return ref; } - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; #ifdef MYSQL_SERVER @@ -2332,7 +2344,7 @@ public: class Cached_item_field :public Cached_item { - char *buff; + uchar *buff; Field *field; uint length; @@ -2340,7 +2352,7 @@ public: Cached_item_field(Item_field *item) { field= item->field; - buff= (char*) sql_calloc(length=field->pack_length()); + buff= (uchar*) sql_calloc(length=field->pack_length()); } bool cmp(void); }; @@ -2364,13 +2376,13 @@ public: int save_in_field(Field *field_arg, bool no_conversions); table_map used_tables() const { return (table_map)0L; } - bool walk(Item_processor processor, bool walk_subquery, byte *args) + bool walk(Item_processor processor, bool walk_subquery, uchar *args) { return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); } - Item *transform(Item_transformer transformer, byte *args); + Item *transform(Item_transformer transformer, uchar *args); }; /* @@ -2404,7 +2416,7 @@ public: */ table_map used_tables() const { return RAND_TABLE_BIT; } - bool walk(Item_processor processor, bool walk_subquery, byte *args) + bool walk(Item_processor processor, bool walk_subquery, uchar *args) { return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); @@ -2692,6 +2704,7 @@ class Item_type_holder: public Item protected: TYPELIB *enum_set_typelib; enum_field_types fld_type; + Field::geometry_type geometry_type; void get_full_info(Item *item); @@ -2711,6 +2724,7 @@ public: Field *make_field_by_type(TABLE *table); static uint32 display_length(Item *item); static enum_field_types get_real_type(Item *); + Field::geometry_type get_geometry_type() { return geometry_type; }; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4a18de8ce4f..543bc827c48 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -531,8 +531,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) which would be transformed to: WHERE col= 'j' */ - (*a)->walk(&Item::set_no_const_sub, FALSE, (byte*) 0); - (*b)->walk(&Item::set_no_const_sub, FALSE, (byte*) 0); + (*a)->walk(&Item::set_no_const_sub, FALSE, (uchar*) 0); + (*b)->walk(&Item::set_no_const_sub, FALSE, (uchar*) 0); } break; } @@ -560,7 +560,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) { if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC) { - precision= 5 * log_01[max((*a)->decimals, (*b)->decimals)]; + precision= 5 / log_10[max((*a)->decimals, (*b)->decimals) + 1]; if (func == &Arg_comparator::compare_real) func= &Arg_comparator::compare_real_fixed; else if (func == &Arg_comparator::compare_e_real) @@ -819,7 +819,12 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, { value= item->val_int(); *is_null= item->null_value; - if (item->field_type() == MYSQL_TYPE_DATE) + /* + Item_date_add_interval may return MYSQL_TYPE_STRING as the result + field type. To detect that the DATE value has been returned we + compare it with 1000000L - any DATE value should be less than it. + */ + if (item->field_type() == MYSQL_TYPE_DATE || value < 100000000L) value*= 1000000L; } else @@ -1767,6 +1772,7 @@ void Item_func_between::fix_length_and_dec() int i; bool datetime_found= FALSE; compare_as_dates= TRUE; + THD *thd= current_thd; /* As some compare functions are generated after sql_yacc, @@ -1805,6 +1811,23 @@ void Item_func_between::fix_length_and_dec() ge_cmp.set_datetime_cmp_func(args, args + 1); le_cmp.set_datetime_cmp_func(args, args + 2); } + else if (args[0]->real_item()->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) + { + Field *field=((Item_field*) (args[0]->real_item()))->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } @@ -2435,7 +2458,7 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) Item_func_case::val_int() -> Item_func_case::find_item() */ #ifndef EMBEDDED_LIBRARY - char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2]; + uchar buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2]; #endif bool res= Item_func::fix_fields(thd, ref); /* @@ -2775,7 +2798,7 @@ static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b) int in_vector::find(Item *item) { - byte *result=get_value(item); + uchar *result=get_value(item); if (!result || !used_count) return 0; // Null value @@ -2830,9 +2853,9 @@ void in_string::set(uint pos,Item *item) } -byte *in_string::get_value(Item *item) +uchar *in_string::get_value(Item *item) { - return (byte*) item->val_str(&tmp); + return (uchar*) item->val_str(&tmp); } in_row::in_row(uint elements, Item * item) @@ -2854,12 +2877,12 @@ in_row::~in_row() delete [] (cmp_item_row*) base; } -byte *in_row::get_value(Item *item) +uchar *in_row::get_value(Item *item) { tmp.store_value(item); if (item->is_null()) return 0; - return (byte *)&tmp; + return (uchar *)&tmp; } void in_row::set(uint pos, Item *item) @@ -2882,13 +2905,13 @@ void in_longlong::set(uint pos,Item *item) buff->unsigned_flag= item->unsigned_flag; } -byte *in_longlong::get_value(Item *item) +uchar *in_longlong::get_value(Item *item) { tmp.val= item->val_int(); if (item->null_value) return 0; tmp.unsigned_flag= item->unsigned_flag; - return (byte*) &tmp; + return (uchar*) &tmp; } void in_datetime::set(uint pos,Item *item) @@ -2901,7 +2924,7 @@ void in_datetime::set(uint pos,Item *item) buff->unsigned_flag= 1L; } -byte *in_datetime::get_value(Item *item) +uchar *in_datetime::get_value(Item *item) { bool is_null; Item **tmp_item= lval_cache ? &lval_cache : &item; @@ -2909,7 +2932,7 @@ byte *in_datetime::get_value(Item *item) if (item->null_value) return 0; tmp.unsigned_flag= 1L; - return (byte*) &tmp; + return (uchar*) &tmp; } in_double::in_double(uint elements) @@ -2921,12 +2944,12 @@ void in_double::set(uint pos,Item *item) ((double*) base)[pos]= item->val_real(); } -byte *in_double::get_value(Item *item) +uchar *in_double::get_value(Item *item) { tmp= item->val_real(); if (item->null_value) return 0; /* purecov: inspected */ - return (byte*) &tmp; + return (uchar*) &tmp; } @@ -2948,12 +2971,12 @@ void in_decimal::set(uint pos, Item *item) } -byte *in_decimal::get_value(Item *item) +uchar *in_decimal::get_value(Item *item) { my_decimal *result= item->val_decimal(&val); if (item->null_value) return 0; - return (byte *)result; + return (uchar *)result; } @@ -3603,7 +3626,7 @@ Item_cond::fix_fields(THD *thd, Item **ref) List_iterator<Item> li(list); Item *item; #ifndef EMBEDDED_LIBRARY - char buff[sizeof(char*)]; // Max local vars in function + uchar buff[sizeof(char*)]; // Max local vars in function #endif not_null_tables_cache= used_tables_cache= 0; const_item_cache= 1; @@ -3670,7 +3693,7 @@ Item_cond::fix_fields(THD *thd, Item **ref) return FALSE; } -bool Item_cond::walk(Item_processor processor, bool walk_subquery, byte *arg) +bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg) { List_iterator_fast<Item> li(list); Item *item; @@ -3702,7 +3725,7 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, byte *arg) Item returned as the result of transformation of the root node */ -Item *Item_cond::transform(Item_transformer transformer, byte *arg) +Item *Item_cond::transform(Item_transformer transformer, uchar *arg) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); @@ -3753,8 +3776,8 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) Item returned as the result of transformation of the root node */ -Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, - Item_transformer transformer, byte *arg_t) +Item *Item_cond::compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t) { if (!(this->*analyzer)(arg_p)) return 0; @@ -3767,7 +3790,7 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ - byte *arg_v= *arg_p; + uchar *arg_v= *arg_p; Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && new_item != item) li.replace(new_item); @@ -5001,7 +5024,7 @@ void Item_equal::fix_length_and_dec() item->collation.collation); } -bool Item_equal::walk(Item_processor processor, bool walk_subquery, byte *arg) +bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg) { List_iterator_fast<Item_field> it(fields); Item *item; @@ -5013,7 +5036,7 @@ bool Item_equal::walk(Item_processor processor, bool walk_subquery, byte *arg) return Item_func::walk(processor, walk_subquery, arg); } -Item *Item_equal::transform(Item_transformer transformer, byte *arg) +Item *Item_equal::transform(Item_transformer transformer, uchar *arg) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8db962a4e2c..60f2ac6321d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -355,8 +355,8 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} - bool subst_argument_checker(byte **arg) { return TRUE; } + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + bool subst_argument_checker(uchar **arg) { return TRUE; } }; class Item_func_not :public Item_bool_func @@ -367,7 +367,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} void print(String *str); }; @@ -572,7 +572,7 @@ public: return this; } bool eq(const Item *item, bool binary_cmp) const; - bool subst_argument_checker(byte **arg) { return TRUE; } + bool subst_argument_checker(uchar **arg) { return TRUE; } }; @@ -598,7 +598,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -610,7 +610,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } void print(String *str) { Item_func::print(str); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -673,7 +673,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -714,7 +714,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; /* Functions to handle the optimized IN */ @@ -739,7 +739,7 @@ public: count(elements), used_count(elements) {} virtual ~in_vector() {} virtual void set(uint pos,Item *item)=0; - virtual byte *get_value(Item *item)=0; + virtual uchar *get_value(Item *item)=0; void sort() { qsort2(base,used_count,size,compare,collation); @@ -782,7 +782,7 @@ public: in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs); ~in_string(); void set(uint pos,Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); Item* create_item() { return new Item_string(collation); @@ -812,7 +812,7 @@ protected: public: in_longlong(uint elements); void set(uint pos,Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); Item* create_item() { @@ -853,7 +853,7 @@ public: :in_longlong(elements), thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}; void set(uint pos,Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); }; @@ -863,7 +863,7 @@ class in_double :public in_vector public: in_double(uint elements); void set(uint pos,Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); Item *create_item() { return new Item_float(0.0); @@ -882,7 +882,7 @@ class in_decimal :public in_vector public: in_decimal(uint elements); void set(uint pos, Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); Item *create_item() { return new Item_decimal(0, FALSE); @@ -1141,7 +1141,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *bool_arg) { return FALSE;} + bool check_partition_func_processor(uchar *bool_arg) { return FALSE;} void cleanup() { uint i; @@ -1222,7 +1222,7 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class cmp_item_row :public cmp_item @@ -1249,9 +1249,9 @@ public: in_row(uint elements, Item *); ~in_row(); void set(uint pos,Item *item); - byte *get_value(Item *item); + uchar *get_value(Item *item); friend void Item_func_in::fix_length_and_dec(); - Item_result result_type() { return ROW_RESULT; }; + Item_result result_type() { return ROW_RESULT; } }; /* Functions used by where clause */ @@ -1294,7 +1294,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -1321,7 +1321,7 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } - bool check_partition_func_processor(byte *int_arg) {return TRUE;} + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1344,7 +1344,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -1383,7 +1383,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; #ifdef USE_REGEX @@ -1406,7 +1406,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; #else @@ -1459,14 +1459,14 @@ public: COND **conds); void top_level_item() { abort_on_null=1; } void copy_andor_arguments(THD *thd, Item_cond *item); - bool walk(Item_processor processor, bool walk_subquery, byte *arg); - Item *transform(Item_transformer transformer, byte *arg); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); + Item *transform(Item_transformer transformer, uchar *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} - bool subst_argument_checker(byte **arg) { return TRUE; } - Item *compile(Item_analyzer analyzer, byte **arg_p, - Item_transformer transformer, byte *arg_t); + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + bool subst_argument_checker(uchar **arg) { return TRUE; } + Item *compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t); }; @@ -1575,8 +1575,8 @@ public: void fix_length_and_dec(); bool fix_fields(THD *thd, Item **ref); void update_used_tables(); - bool walk(Item_processor processor, bool walk_subquery, byte *arg); - Item *transform(Item_transformer transformer, byte *arg); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); + Item *transform(Item_transformer transformer, uchar *arg); void print(String *str); CHARSET_INFO *compare_collation() { return fields.head()->collation.collation; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 62f44996f4b..0d85847cff7 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2141,6 +2141,19 @@ protected: }; +class Create_func_uuid_short : public Create_func_arg0 +{ +public: + virtual Item *create(THD *thd); + + static Create_func_uuid_short s_singleton; + +protected: + Create_func_uuid_short() {} + virtual ~Create_func_uuid_short() {} +}; + + class Create_func_version : public Create_func_arg0 { public: @@ -2341,7 +2354,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list) if (item_list != NULL) arg_count= item_list->elements; - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION) || (udf->type == UDFTYPE_AGGREGATE)); @@ -4528,11 +4541,23 @@ Create_func_uuid Create_func_uuid::s_singleton; Item* Create_func_uuid::create(THD *thd) { - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); + thd->lex->safe_to_cache_query= 0; return new (thd->mem_root) Item_func_uuid(); } +Create_func_uuid_short Create_func_uuid_short::s_singleton; + +Item* +Create_func_uuid_short::create(THD *thd) +{ + thd->lex->set_stmt_unsafe(); + thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_uuid_short(); +} + + Create_func_version Create_func_version::s_singleton; Item* @@ -4872,6 +4897,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("UPDATEXML") }, BUILDER(Create_func_xml_update)}, { { C_STRING_WITH_LEN("UPPER") }, BUILDER(Create_func_ucase)}, { { C_STRING_WITH_LEN("UUID") }, BUILDER(Create_func_uuid)}, + { { C_STRING_WITH_LEN("UUID_SHORT") }, BUILDER(Create_func_uuid_short)}, { { C_STRING_WITH_LEN("VERSION") }, BUILDER(Create_func_version)}, { { C_STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)}, { { C_STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)}, @@ -4885,12 +4911,13 @@ static Native_func_registry func_array[] = static HASH native_functions_hash; -extern "C" byte* -get_native_fct_hash_key(const byte *buff, uint *length, my_bool /* unused */) +extern "C" uchar* +get_native_fct_hash_key(const uchar *buff, size_t *length, + my_bool /* unused */) { Native_func_registry *func= (Native_func_registry*) buff; *length= func->name.length; - return (byte*) func->name.str; + return (uchar*) func->name.str; } /* @@ -4917,7 +4944,7 @@ int item_create_init() for (func= func_array; func->builder != NULL; func++) { - if (my_hash_insert(& native_functions_hash, (byte*) func)) + if (my_hash_insert(& native_functions_hash, (uchar*) func)) DBUG_RETURN(1); } @@ -4925,8 +4952,8 @@ int item_create_init() for (uint i=0 ; i < native_functions_hash.records ; i++) { func= (Native_func_registry*) hash_element(& native_functions_hash, i); - DBUG_PRINT("info", ("native function %s, length %d", - func->name.str, func->name.length)); + DBUG_PRINT("info", ("native function: %s length: %u", + func->name.str, (uint) func->name.length)); } #endif @@ -4954,7 +4981,7 @@ find_native_function_builder(THD *thd, LEX_STRING name) /* Thread safe */ func= (Native_func_registry*) hash_search(& native_functions_hash, - (byte*) name.str, + (uchar*) name.str, name.length); if (func) diff --git a/sql/item_func.cc b/sql/item_func.cc index 271b4d784e7..fb2f361f676 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -36,7 +36,6 @@ #define sp_restore_security_context(A,B) while (0) {} #endif - bool check_reserved_words(LEX_STRING *name) { if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") || @@ -143,7 +142,7 @@ Item_func::fix_fields(THD *thd, Item **ref) DBUG_ASSERT(fixed == 0); Item **arg,**arg_end; #ifndef EMBEDDED_LIBRARY // Avoid compiler warning - char buff[STACK_BUFF_ALLOC]; // Max argument in function + uchar buff[STACK_BUFF_ALLOC]; // Max argument in function #endif used_tables_cache= not_null_tables_cache= 0; @@ -196,7 +195,7 @@ Item_func::fix_fields(THD *thd, Item **ref) bool Item_func::walk(Item_processor processor, bool walk_subquery, - byte *argument) + uchar *argument) { if (arg_count) { @@ -259,7 +258,7 @@ void Item_func::traverse_cond(Cond_traverser traverser, Item returned as the result of transformation of the root node */ -Item *Item_func::transform(Item_transformer transformer, byte *argument) +Item *Item_func::transform(Item_transformer transformer, uchar *argument) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); @@ -312,8 +311,8 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) Item returned as the result of transformation of the root node */ -Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, - Item_transformer transformer, byte *arg_t) +Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t) { if (!(this->*analyzer)(arg_p)) return 0; @@ -326,7 +325,7 @@ Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ - byte *arg_v= *arg_p; + uchar *arg_v= *arg_p; Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && *arg != new_item) current_thd->change_item_tree(arg, new_item); @@ -466,7 +465,7 @@ Field *Item_func::tmp_table_field(TABLE *table) } -bool Item_func::is_expensive_processor(byte *arg) +bool Item_func::is_expensive_processor(uchar *arg) { return is_expensive(); } @@ -994,6 +993,8 @@ longlong Item_func_unsigned::val_int() my_decimal tmp, *dec= args[0]->val_decimal(&tmp); if (!(null_value= args[0]->null_value)) my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value); + else + value= 0; return value; } else if (args[0]->cast_to_int_type() != STRING_RESULT || @@ -1953,7 +1954,13 @@ void Item_func_round::fix_length_and_dec() { max_length= args[0]->max_length; decimals= args[0]->decimals; - hybrid_type= REAL_RESULT; + if (args[0]->result_type() == DECIMAL_RESULT) + { + max_length++; + hybrid_type= DECIMAL_RESULT; + } + else + hybrid_type= REAL_RESULT; return; } @@ -2802,7 +2809,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, uint arg_count, Item **arguments) { #ifndef EMBEDDED_LIBRARY // Avoid compiler warning - char buff[STACK_BUFF_ALLOC]; // Max argument in function + uchar buff[STACK_BUFF_ALLOC]; // Max argument in function #endif DBUG_ENTER("Item_udf_func::fix_fields"); @@ -3240,8 +3247,8 @@ static HASH hash_user_locks; class User_level_lock { - char *key; - uint key_length; + uchar *key; + size_t key_length; public: int count; @@ -3250,16 +3257,16 @@ public: my_thread_id thread_id; void set_thread(THD *thd) { thread_id= thd->thread_id; } - User_level_lock(const char *key_arg,uint length, ulong id) + User_level_lock(const uchar *key_arg,uint length, ulong id) :key_length(length),count(1),locked(1), thread_id(id) { - key=(char*) my_memdup((byte*) key_arg,length,MYF(0)); + key= (uchar*) my_memdup(key_arg,length,MYF(0)); pthread_cond_init(&cond,NULL); if (key) { - if (my_hash_insert(&hash_user_locks,(byte*) this)) + if (my_hash_insert(&hash_user_locks,(uchar*) this)) { - my_free((gptr) key,MYF(0)); + my_free(key,MYF(0)); key=0; } } @@ -3268,22 +3275,22 @@ public: { if (key) { - hash_delete(&hash_user_locks,(byte*) this); - my_free((gptr) key,MYF(0)); + hash_delete(&hash_user_locks,(uchar*) this); + my_free(key, MYF(0)); } pthread_cond_destroy(&cond); } inline bool initialized() { return key != 0; } friend void item_user_lock_release(User_level_lock *ull); - friend char *ull_get_key(const User_level_lock *ull, uint *length, - my_bool not_used); + friend uchar *ull_get_key(const User_level_lock *ull, size_t *length, + my_bool not_used); }; -char *ull_get_key(const User_level_lock *ull, uint *length, - my_bool not_used __attribute__((unused))) +uchar *ull_get_key(const User_level_lock *ull, size_t *length, + my_bool not_used __attribute__((unused))) { - *length=(uint) ull->key_length; - return (char*) ull->key; + *length= ull->key_length; + return ull->key; } @@ -3353,8 +3360,8 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) THD* thd=current_thd; User_level_lock* ull; struct timespec abstime; - int lock_name_len; - lock_name_len=strlen(lock_name); + size_t lock_name_len; + lock_name_len= strlen(lock_name); pthread_mutex_lock(&LOCK_user_locks); if (thd->ull) @@ -3369,8 +3376,9 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) this case, we will not be waiting, but rather, just waste CPU and memory on the whole deal */ - if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, lock_name, - lock_name_len)))) + if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, + (uchar*) lock_name, + lock_name_len)))) { pthread_mutex_unlock(&LOCK_user_locks); return; @@ -3437,6 +3445,7 @@ longlong Item_func_get_lock::val_int() THD *thd=current_thd; User_level_lock *ull; int error; + DBUG_ENTER("Item_func_get_lock::val_int"); /* In slave thread no need to get locks, everything is serialized. Anyway @@ -3446,7 +3455,7 @@ longlong Item_func_get_lock::val_int() it's not guaranteed to be same as on master. */ if (thd->slave_thread) - return 1; + DBUG_RETURN(1); pthread_mutex_lock(&LOCK_user_locks); @@ -3454,8 +3463,10 @@ longlong Item_func_get_lock::val_int() { pthread_mutex_unlock(&LOCK_user_locks); null_value=1; - return 0; + DBUG_RETURN(0); } + DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(), + (long) thd->real_id)); null_value=0; if (thd->ull) @@ -3465,23 +3476,26 @@ longlong Item_func_get_lock::val_int() } if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks, - (byte*) res->ptr(), - res->length())))) + (uchar*) res->ptr(), + (size_t) res->length())))) { - ull=new User_level_lock(res->ptr(),res->length(), thd->thread_id); + ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(), + thd->thread_id); if (!ull || !ull->initialized()) { delete ull; pthread_mutex_unlock(&LOCK_user_locks); null_value=1; // Probably out of memory - return 0; + DBUG_RETURN(0); } ull->set_thread(thd); thd->ull=ull; pthread_mutex_unlock(&LOCK_user_locks); - return 1; // Got new lock + DBUG_PRINT("info", ("made new lock")); + DBUG_RETURN(1); // Got new lock } ull->count++; + DBUG_PRINT("info", ("ull->count=%d", ull->count)); /* Structure is now initialized. Try to get the lock. @@ -3495,9 +3509,13 @@ longlong Item_func_get_lock::val_int() error= 0; while (ull->locked && !thd->killed) { + DBUG_PRINT("info", ("waiting on lock")); error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime); if (error == ETIMEDOUT || error == ETIME) + { + DBUG_PRINT("info", ("lock wait timeout")); break; + } error= 0; } @@ -3521,6 +3539,7 @@ longlong Item_func_get_lock::val_int() ull->thread_id= thd->thread_id; thd->ull=ull; error=0; + DBUG_PRINT("info", ("got the lock")); } pthread_mutex_unlock(&LOCK_user_locks); @@ -3530,7 +3549,7 @@ longlong Item_func_get_lock::val_int() thd->mysys_var->current_cond= 0; pthread_mutex_unlock(&thd->mysys_var->mutex); - return !error ? 1 : 0; + DBUG_RETURN(!error ? 1 : 0); } @@ -3548,32 +3567,40 @@ longlong Item_func_release_lock::val_int() String *res=args[0]->val_str(&value); User_level_lock *ull; longlong result; + THD *thd=current_thd; + DBUG_ENTER("Item_func_release_lock::val_int"); if (!res || !res->length()) { null_value=1; - return 0; + DBUG_RETURN(0); } + DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr())); null_value=0; result=0; pthread_mutex_lock(&LOCK_user_locks); if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, - (const byte*) res->ptr(), - res->length())))) + (const uchar*) res->ptr(), + (size_t) res->length())))) { null_value=1; } else { + DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu", + (int) ull->locked, + (long)ull->thread_id, + (long)thd->thread_id)); if (ull->locked && current_thd->thread_id == ull->thread_id) { + DBUG_PRINT("info", ("release lock")); result=1; // Release is ok item_user_lock_release(ull); - current_thd->ull=0; + thd->ull=0; } } pthread_mutex_unlock(&LOCK_user_locks); - return result; + DBUG_RETURN(result); } @@ -3704,7 +3731,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, { user_var_entry *entry; - if (!(entry = (user_var_entry*) hash_search(hash, (byte*) name.str, + if (!(entry = (user_var_entry*) hash_search(hash, (uchar*) name.str, name.length)) && create_if_not_exists) { @@ -3734,7 +3761,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->used_query_id=current_thd->query_id; entry->type=STRING_RESULT; memcpy(entry->name.str, name.str, name.length+1); - if (my_hash_insert(hash,(byte*) entry)) + if (my_hash_insert(hash,(uchar*) entry)) { my_free((char*) entry,MYF(0)); return 0; @@ -3796,6 +3823,23 @@ Item_func_set_user_var::fix_length_and_dec() /* + Mark field in read_map + + NOTES + This is used by filesort to register used fields in a a temporary + column read set or to register used fields in a view +*/ + +bool Item_func_set_user_var::register_field_in_read_map(uchar *arg) +{ + TABLE *table= (TABLE *) arg; + if (result_field->table == table || !table) + bitmap_set_bit(result_field->table->read_set, result_field->field_index); + return 0; +} + + +/* Set value to user variable. SYNOPSYS @@ -4031,7 +4075,8 @@ bool Item_func_set_user_var::check(bool use_result_field) { DBUG_ENTER("Item_func_set_user_var::check"); - DBUG_ASSERT(!use_result_field || result_field); + if (use_result_field && !result_field) + use_result_field= FALSE; switch (cached_result_type) { case REAL_RESULT: @@ -4175,6 +4220,40 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) } +double Item_func_set_user_var::val_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return entry->val_real(&null_value); +} + +longlong Item_func_set_user_var::val_int_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return entry->val_int(&null_value); +} + +String *Item_func_set_user_var::str_result(String *str) +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return entry->val_str(&null_value, str, decimals); +} + + +my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return entry->val_decimal(&null_value, val); +} + + void Item_func_set_user_var::print(String *str) { str->append(STRING_WITH_LEN("(@")); @@ -4257,9 +4336,11 @@ void Item_func_set_user_var::make_field(Send_field *tmp_field) TRUE Error */ -int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions) +int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions, + bool can_use_result_field) { - bool use_result_field= (result_field && result_field != field); + bool use_result_field= (!can_use_result_field ? 0 : + (result_field && result_field != field)); int error; /* Update the value of the user variable */ @@ -4451,7 +4532,7 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command, > set @a:=1; > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1); We have to write to binlog value @a= 1. - + We allocate the user_var_event on user_var_events_alloc pool, not on the this-statement-execution pool because in SPs user_var_event objects may need to be valid after current [SP] statement execution pool is @@ -4461,7 +4542,7 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command, if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) alloc_root(thd->user_var_events_alloc, size))) goto err; - + user_var_event->value= (char*) user_var_event + ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)); user_var_event->user_var_event= var_entry; @@ -4481,9 +4562,9 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command, } /* Mark that this variable has been used by this query */ var_entry->used_query_id= thd->query_id; - if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event)) + if (insert_dynamic(&thd->user_var_events, (uchar*) &user_var_event)) goto err; - + *out_entry= var_entry; return 0; @@ -4492,7 +4573,6 @@ err: return 1; } - void Item_func_get_user_var::fix_length_and_dec() { THD *thd=current_thd; @@ -4503,10 +4583,19 @@ void Item_func_get_user_var::fix_length_and_dec() error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry); + /* + If the variable didn't exist it has been created as a STRING-type. + 'var_entry' is NULL only if there occured an error during the call to + get_var_with_binlog. + */ if (var_entry) { + m_cached_result_type= var_entry->type; + unsigned_flag= var_entry->unsigned_flag; + max_length= var_entry->length; + collation.set(var_entry->collation); - switch (var_entry->type) { + switch(m_cached_result_type) { case REAL_RESULT: max_length= DBL_DIG + 8; break; @@ -4531,6 +4620,8 @@ void Item_func_get_user_var::fix_length_and_dec() { collation.set(&my_charset_bin, DERIVATION_IMPLICIT); null_value= 1; + m_cached_result_type= STRING_RESULT; + max_length= MAX_BLOB_WIDTH; } if (error) @@ -4548,12 +4639,7 @@ bool Item_func_get_user_var::const_item() const enum Item_result Item_func_get_user_var::result_type() const { - user_var_entry *entry; - if (!(entry = (user_var_entry*) hash_search(¤t_thd->user_vars, - (byte*) name.str, - name.length))) - return STRING_RESULT; - return entry->type; + return m_cached_result_type; } @@ -4988,7 +5074,7 @@ double Item_func_match::val_real() if ((null_value= (a == 0)) || !a->length()) DBUG_RETURN(0); DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, - (byte *)a->ptr(), a->length())); + (uchar *)a->ptr(), a->length())); } DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, table->record[0], 0)); @@ -5103,8 +5189,8 @@ longlong Item_func_is_free_lock::val_int() } pthread_mutex_lock(&LOCK_user_locks); - ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(), - res->length()); + ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(), + (size_t) res->length()); pthread_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 1; @@ -5122,8 +5208,8 @@ longlong Item_func_is_used_lock::val_int() return 0; pthread_mutex_lock(&LOCK_user_locks); - ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(), - res->length()); + ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(), + (size_t) res->length()); pthread_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 0; @@ -5183,10 +5269,11 @@ Item_func_sp::func_name() const { THD *thd= current_thd; /* Calculate length to avoid reallocation of string for sure */ - uint len= ((m_name->m_explicit_name ? m_name->m_db.length : 0 + + uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) + m_name->m_name.length)*2 + //characters*quoting 2 + // ` and ` - 1 + // . + (m_name->m_explicit_name ? + 3 : 0) + // '`', '`' and '.' for the db 1 + // end of string ALIGN_SIZE(1)); // to avoid String reallocation String qname((char *)alloc_root(thd->mem_root, len), len, @@ -5221,14 +5308,13 @@ Item_func_sp::func_name() const @retval TRUE is returned on an error @retval FALSE is returned on success. */ + bool Item_func_sp::init_result_field(THD *thd) { - DBUG_ENTER("Item_func_sp::init_result_field"); - LEX_STRING empty_name= { C_STRING_WITH_LEN("") }; - TABLE_SHARE *share; + DBUG_ENTER("Item_func_sp::init_result_field"); DBUG_ASSERT(m_sp == NULL); DBUG_ASSERT(sp_result_field == NULL); @@ -5255,30 +5341,34 @@ Item_func_sp::init_result_field(THD *thd) share->table_cache_key = empty_name; share->table_name = empty_name; - if (!(sp_result_field= m_sp->create_result_field(max_length, name, dummy_table))) + if (!(sp_result_field= m_sp->create_result_field(max_length, name, + dummy_table))) { DBUG_RETURN(TRUE); } if (sp_result_field->pack_length() > sizeof(result_buf)) { - sp_result_field->move_field(sql_alloc(sp_result_field->pack_length())); - } else { - sp_result_field->move_field(result_buf); + void *tmp; + if (!(tmp= sql_alloc(sp_result_field->pack_length()))) + DBUG_RETURN(TRUE); + sp_result_field->move_field((uchar*) tmp); } + else + sp_result_field->move_field(result_buf); sp_result_field->null_ptr= (uchar *) &null_value; sp_result_field->null_bit= 1; - - DBUG_RETURN(FALSE); } + /** @brief Initialize local members with values from the Field interface. @note called from Item::fix_fields. */ + void Item_func_sp::fix_length_and_dec() { DBUG_ENTER("Item_func_sp::fix_length_and_dec"); @@ -5293,6 +5383,7 @@ void Item_func_sp::fix_length_and_dec() DBUG_VOID_RETURN; } + /** @brief Execute function & store value in field. @@ -5306,18 +5397,14 @@ Item_func_sp::execute() { THD *thd= current_thd; - /* - Get field in virtual tmp table to store result. Create the field if - invoked first time. - */ - - /* Execute function and store the return value in the field. */ if (execute_impl(thd)) { null_value= 1; context->process_error(thd); + if (thd->killed) + thd->send_kill_message(); return TRUE; } @@ -5511,3 +5598,40 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) } DBUG_RETURN(res); } + + +/* + uuid_short handling. + + The short uuid is defined as a longlong that contains the following bytes: + + Bytes Comment + 1 Server_id & 255 + 4 Startup time of server in seconds + 3 Incrementor + + This means that an uuid is guaranteed to be unique + even in a replication environment if the following holds: + + - The last byte of the server id is unique + - If you between two shutdown of the server don't get more than + an average of 2^24 = 16M calls to uuid_short() per second. +*/ + +ulonglong uuid_value; + +void uuid_short_init() +{ + uuid_value= ((((ulonglong) server_id) << 56) + + (((ulonglong) server_start_time) << 24)); +} + + +longlong Item_func_uuid_short::val_int() +{ + ulonglong val; + pthread_mutex_lock(&LOCK_uuid_generator); + val= uuid_value++; + pthread_mutex_unlock(&LOCK_uuid_generator); + return (longlong) val; +} diff --git a/sql/item_func.h b/sql/item_func.h index b76877f90bc..8fc68f93e12 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -184,13 +184,13 @@ public: { return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); } - bool walk(Item_processor processor, bool walk_subquery, byte *arg); - Item *transform(Item_transformer transformer, byte *arg); - Item* compile(Item_analyzer analyzer, byte **arg_p, - Item_transformer transformer, byte *arg_t); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); + Item *transform(Item_transformer transformer, uchar *arg); + Item* compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); - bool is_expensive_processor(byte *arg); + bool is_expensive_processor(uchar *arg); virtual bool is_expensive() { return 0; } }; @@ -253,7 +253,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -266,7 +266,7 @@ class Item_num_op :public Item_func_numhybrid void print(String *str) { print_op(str); } void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -311,7 +311,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -345,7 +345,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -414,7 +414,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -488,7 +488,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -498,7 +498,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -509,7 +509,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -519,7 +519,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -529,7 +529,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -539,7 +539,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -549,7 +549,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -559,7 +559,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_asin :public Item_dec_func @@ -568,7 +568,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_atan :public Item_dec_func @@ -578,7 +578,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_cos :public Item_dec_func @@ -587,7 +587,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_sin :public Item_dec_func @@ -596,7 +596,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_tan :public Item_dec_func @@ -605,7 +605,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_integer :public Item_int_func @@ -684,7 +684,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -699,7 +699,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -725,7 +725,7 @@ public: void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } bool result_as_longlong() { return compare_as_dates; }; - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} uint cmp_datetimes(ulonglong *value); }; @@ -781,7 +781,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_bit_length :public Item_func_length @@ -801,7 +801,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_coercibility :public Item_int_func @@ -825,7 +825,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -850,7 +850,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_ord :public Item_int_func @@ -860,7 +860,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_find_in_set :public Item_int_func @@ -874,7 +874,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -886,7 +886,7 @@ public: Item_func_bit(Item *a) :Item_int_func(a) {} void fix_length_and_dec() { unsigned_flag= 1; } void print(String *str) { print_op(str); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_bit_or :public Item_func_bit @@ -912,7 +912,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_shift_left :public Item_func_bit @@ -1236,6 +1236,10 @@ public: longlong val_int(); String *val_str(String *str); my_decimal *val_decimal(my_decimal *); + double val_result(); + longlong val_int_result(); + String *str_result(String *str); + my_decimal *val_decimal_result(my_decimal *); bool update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool send(Protocol *protocol, String *str_arg); @@ -1248,7 +1252,14 @@ public: void print(String *str); void print_as_stmt(String *str); const char *func_name() const { return "set_user_var"; } - int save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions, + bool can_use_result_field); + int save_in_field(Field *field, bool no_conversions) + { + return save_in_field(field, no_conversions, 1); + } + void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); } + bool register_field_in_read_map(uchar *arg); }; @@ -1256,11 +1267,12 @@ class Item_func_get_user_var :public Item_func, private Settable_routine_parameter { user_var_entry *var_entry; + Item_result m_cached_result_type; public: LEX_STRING name; // keep it public Item_func_get_user_var(LEX_STRING a): - Item_func(), name(a) {} + Item_func(), m_cached_result_type(STRING_RESULT), name(a) {} enum Functype functype() const { return GUSERVAR_FUNC; } LEX_STRING get_name() { return name; } double val_real(); @@ -1274,13 +1286,11 @@ public: We must always return variables as strings to guard against selects of type select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b) */ - enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } const char *func_name() const { return "get_user_var"; } bool const_item() const; table_map used_tables() const { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, bool binary_cmp) const; - private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it); @@ -1353,7 +1363,7 @@ public: longlong val_int(); const char *func_name() const { return "inet_aton"; } void fix_length_and_dec() { decimals= 0; max_length= 21; maybe_null= 1; unsigned_flag= 1;} - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -1466,7 +1476,7 @@ private: sp_name *m_name; mutable sp_head *m_sp; TABLE *dummy_table; - char result_buf[64]; + uchar result_buf[64]; /* The result field of the concrete stored function. */ @@ -1540,7 +1550,7 @@ public: return str; } - virtual bool change_context_processor(byte *cntx) + virtual bool change_context_processor(uchar *cntx) { context= (Name_resolution_context *)cntx; return FALSE; } bool sp_check_access(THD * thd); @@ -1560,3 +1570,18 @@ public: const char *func_name() const { return "found_rows"; } void fix_length_and_dec() { decimals= 0; maybe_null=0; } }; + + +void uuid_short_init(); + +class Item_func_uuid_short :public Item_int_func +{ +public: + Item_func_uuid_short() :Item_int_func() {} + const char *func_name() const { return "uuid_short"; } + longlong val_int(); + void fix_length_and_dec() + { max_length= 21; unsigned_flag=1; } + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} +}; + diff --git a/sql/item_row.cc b/sql/item_row.cc index 956556ca783..d1d1011ab2b 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -142,7 +142,7 @@ void Item_row::print(String *str) } -bool Item_row::walk(Item_processor processor, bool walk_subquery, byte *arg) +bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg) { for (uint i= 0; i < arg_count; i++) { @@ -153,7 +153,7 @@ bool Item_row::walk(Item_processor processor, bool walk_subquery, byte *arg) } -Item *Item_row::transform(Item_transformer transformer, byte *arg) +Item *Item_row::transform(Item_transformer transformer, uchar *arg) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); diff --git a/sql/item_row.h b/sql/item_row.h index d55d3ae223f..dd7436888f0 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -67,8 +67,8 @@ public: void update_used_tables(); void print(String *str); - bool walk(Item_processor processor, bool walk_subquery, byte *arg); - Item *transform(Item_transformer transformer, byte *arg); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); + Item *transform(Item_transformer transformer, uchar *arg); uint cols() { return arg_count; } Item* element_index(uint i) { return items[i]; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a1fd79cbfb0..3dc352338a4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -28,6 +28,7 @@ #include "md5.h" #include "sha1.h" #include "my_aes.h" +#include <zlib.h> C_MODE_START #include "../mysys/my_static.h" // For soundex_map C_MODE_END @@ -2220,7 +2221,7 @@ String *Item_func_make_set::val_str(String *str) } -Item *Item_func_make_set::transform(Item_transformer transformer, byte *arg) +Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); @@ -2903,7 +2904,7 @@ String *Item_load_file::val_str(String *str) goto err; if ((file = my_open(file_name->c_ptr(), O_RDONLY, MYF(0))) < 0) goto err; - if (my_read(file, (byte*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP))) + if (my_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP))) { my_close(file, MYF(0)); goto err; @@ -3363,7 +3364,7 @@ String *Item_func_uuid::val_str(String *str) *--s=_dig_vec_lower[mac[i] >> 4]; } randominit(&uuid_rand, tmp + (ulong) server_start_time, - tmp + thd->status_var.bytes_sent); + tmp + (ulong) thd->status_var.bytes_sent); set_clock_seq_str(); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 60e7de42a9d..c036ec490db 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -50,7 +50,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -94,7 +94,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_concat_ws :public Item_str_func @@ -116,7 +116,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -148,13 +148,13 @@ class Item_str_conv :public Item_str_func { protected: uint multiply; - uint (*converter)(CHARSET_INFO *cs, char *src, uint srclen, - char *dst, uint dstlen); + size_t (*converter)(CHARSET_INFO *cs, char *src, size_t srclen, + char *dst, size_t dstlen); String tmp_value; public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -455,7 +455,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -491,12 +491,12 @@ public: void update_used_tables(); const char *func_name() const { return "make_set"; } - bool walk(Item_processor processor, bool walk_subquery, byte *arg) + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return item->walk(processor, walk_subquery, arg) || Item_str_func::walk(processor, walk_subquery, arg); } - Item *transform(Item_transformer transformer, byte *arg); + Item *transform(Item_transformer transformer, uchar *arg); void print(String *str); }; @@ -549,7 +549,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -562,7 +562,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -577,7 +577,7 @@ public: collation.set(default_charset()); max_length= 64; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -594,7 +594,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_unhex :public Item_str_func @@ -614,7 +614,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -638,7 +638,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -678,7 +678,7 @@ public: String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_quote :public Item_str_func @@ -693,7 +693,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_conv_charset :public Item_str_func @@ -794,7 +794,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_uncompressed_length : public Item_int_func diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ab4b4eb6796..000abb313a0 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -149,7 +149,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) DBUG_ASSERT(fixed == 0); engine->set_thd((thd= thd_param)); - if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res)) + if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res)) return TRUE; res= engine->prepare(); @@ -206,7 +206,7 @@ err: bool Item_subselect::walk(Item_processor processor, bool walk_subquery, - byte *argument) + uchar *argument) { if (walk_subquery) @@ -449,7 +449,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) 'upper' select is not really dependent => we remove this dependence */ substitution->walk(&Item::remove_dependence_processor, 0, - (byte *) select_lex->outer_select()); + (uchar *) select_lex->outer_select()); return RES_REDUCE; } return RES_OK; @@ -818,6 +818,11 @@ bool Item_in_subselect::val_bool() if (exec()) { reset(); + /* + Must mark the IN predicate as NULL so as to make sure an enclosing NOT + predicate will return FALSE. See the comments in + subselect_uniquesubquery_engine::copy_ref_key for further details. + */ null_value= 1; return 0; } @@ -1979,10 +1984,38 @@ int subselect_uniquesubquery_engine::scan_table() DESCRIPTION Copy ref key and check for null parts in it. + Depending on the nullability and conversion problems this function + recognizes and processes the following states : + 1. Partial match on top level. This means IN has a value of FALSE + regardless of the data in the subquery table. + Detected by finding a NULL in the left IN operand of a top level + expression. + We may actually skip reading the subquery, so return TRUE to skip + the table scan in subselect_uniquesubquery_engine::exec and make + the value of the IN predicate a NULL (that is equal to FALSE on + top level). + 2. No exact match when IN is nested inside another predicate. + Detected by finding a NULL in the left IN operand when IN is not + a top level predicate. + We cannot have an exact match. But we must proceed further with a + table scan to find out if it's a partial match (and IN has a value + of NULL) or no match (and IN has a value of FALSE). + So we return FALSE to continue with the scan and see if there are + any record that would constitute a partial match (as we cannot + determine that from the index). + 3. Error converting the left IN operand to the column type of the + right IN operand. This counts as no match (and IN has the value of + FALSE). We mark the subquery table cursor as having no more rows + (to ensure that the processing that follows will not find a match) + and return FALSE, so IN is not treated as returning NULL. + RETURN - FALSE - ok, index lookup key without keys copied. - TRUE - an error occured while copying the key + FALSE - The value of the IN predicate is not known. Proceed to find the + value of the IN predicate using the determined values of + null_keypart and table->status. + TRUE - IN predicate has a value of NULL. Stop the processing right there + and return NULL to the outer predicates. */ bool subselect_uniquesubquery_engine::copy_ref_key() @@ -2002,13 +2035,37 @@ bool subselect_uniquesubquery_engine::copy_ref_key() function. */ null_keypart= (*copy)->null_key; - bool top_level= ((Item_in_subselect *) item)->is_top_level_item(); - if (null_keypart && !top_level) - break; - if ((tab->ref.key_err) & 1 || (null_keypart && top_level)) + if (null_keypart) + { + bool top_level= ((Item_in_subselect *) item)->is_top_level_item(); + if (top_level) + { + /* Partial match on top level */ + DBUG_RETURN(1); + } + else + { + /* No exact match when IN is nested inside another predicate */ + break; + } + } + + /* + Check if the error is equal to STORE_KEY_FATAL. This is not expressed + using the store_key::store_key_result enum because ref.key_err is a + boolean and we want to detect both TRUE and STORE_KEY_FATAL from the + space of the union of the values of [TRUE, FALSE] and + store_key::store_key_result. + TODO: fix the variable an return types. + */ + if (tab->ref.key_err & 1) { + /* + Error converting the left IN operand to the column type of the right + IN operand. + */ tab->table->status= STATUS_NOT_FOUND; - DBUG_RETURN(1); + break; } } DBUG_RETURN(0); @@ -2051,10 +2108,20 @@ int subselect_uniquesubquery_engine::exec() int error; TABLE *table= tab->table; empty_result_set= TRUE; + table->status= 0; /* TODO: change to use of 'full_scan' here? */ if (copy_ref_key()) DBUG_RETURN(1); + if (table->status) + { + /* + We know that there will be no rows even if we scan. + Can be set in copy_ref_key. + */ + ((Item_in_subselect *) item)->value= 0; + DBUG_RETURN(0); + } if (null_keypart) DBUG_RETURN(scan_table()); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 7c21eac6ec3..51ab7b8ad42 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -125,7 +125,7 @@ public: */ virtual void reset_value_registration() {} enum_parsing_place place() { return parsing_place; } - bool walk(Item_processor processor, bool walk_subquery, byte *arg); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); /** Get the SELECT_LEX structure associated with this Item. diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f962d067e17..0cb1773ebfa 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -403,7 +403,7 @@ Item *Item_sum::get_tmp_table_item(THD *thd) bool Item_sum::walk (Item_processor processor, bool walk_subquery, - byte *argument) + uchar *argument) { if (arg_count) { @@ -431,7 +431,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, break; case STRING_RESULT: if (max_length/collation.collation->mbmaxlen <= 255 || - convert_blob_length >=UINT_MAX16 || + convert_blob_length > Field_varstring::MAX_SIZE || !convert_blob_length) return make_string_field(table); field= new Field_varstring(convert_blob_length, maybe_null, @@ -912,8 +912,8 @@ void Item_sum_distinct::fix_length_and_dec() bool Item_sum_distinct::setup(THD *thd) { - List<create_field> field_list; - create_field field_def; /* field definition */ + List<Create_field> field_list; + Create_field field_def; /* field definition */ DBUG_ENTER("Item_sum_distinct::setup"); DBUG_ASSERT(tree == 0); @@ -1434,7 +1434,7 @@ my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf) void Item_sum_variance::reset_field() { double nr; - char *res= result_field->ptr; + uchar *res= result_field->ptr; nr= args[0]->val_real(); /* sets null_value as side-effect */ @@ -1457,7 +1457,7 @@ void Item_sum_variance::reset_field() void Item_sum_variance::update_field() { ulonglong field_count; - char *res=result_field->ptr; + uchar *res=result_field->ptr; double nr= args[0]->val_real(); /* sets null_value as side-effect */ @@ -1821,7 +1821,7 @@ bool Item_sum_and::add() void Item_sum_num::reset_field() { double nr= args[0]->val_real(); - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (maybe_null) { @@ -1943,7 +1943,7 @@ void Item_sum_sum::reset_field() void Item_sum_count::reset_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; longlong nr=0; if (!args[0]->maybe_null || !args[0]->is_null()) @@ -1954,7 +1954,7 @@ void Item_sum_count::reset_field() void Item_sum_avg::reset_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (hybrid_type == DECIMAL_RESULT) { longlong tmp; @@ -1995,7 +1995,7 @@ void Item_sum_bit::reset_field() void Item_sum_bit::update_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; bits= uint8korr(res); add(); int8store(res, bits); @@ -2030,7 +2030,7 @@ void Item_sum_sum::update_field() else { double old_nr,nr; - char *res=result_field->ptr; + uchar *res=result_field->ptr; float8get(old_nr,res); nr= args[0]->val_real(); @@ -2047,7 +2047,7 @@ void Item_sum_sum::update_field() void Item_sum_count::update_field() { longlong nr; - char *res=result_field->ptr; + uchar *res=result_field->ptr; nr=sint8korr(res); if (!args[0]->maybe_null || !args[0]->is_null()) @@ -2059,7 +2059,7 @@ void Item_sum_count::update_field() void Item_sum_avg::update_field() { longlong field_count; - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (hybrid_type == DECIMAL_RESULT) { my_decimal value, *arg_val= args[0]->val_decimal(&value); @@ -2228,7 +2228,7 @@ double Item_avg_field::val_real() // fix_fields() never calls for this Item double nr; longlong count; - char *res; + uchar *res; if (hybrid_type == DECIMAL_RESULT) return val_real_from_decimal(); @@ -2361,10 +2361,10 @@ double Item_variance_field::val_real() ** COUNT(DISTINCT ...) ****************************************************************************/ -int simple_str_key_cmp(void* arg, byte* key1, byte* key2) +int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2) { Field *f= (Field*) arg; - return f->cmp((const char*)key1, (const char*)key2); + return f->cmp(key1, key2); } /* @@ -2374,7 +2374,7 @@ int simple_str_key_cmp(void* arg, byte* key1, byte* key2) static */ -int composite_key_cmp(void* arg, byte* key1, byte* key2) +int composite_key_cmp(void* arg, uchar* key1, uchar* key2) { Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg; Field **field = item->table->field; @@ -2384,7 +2384,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) { Field* f = *field; int len = *lengths++; - int res = f->cmp((char *) key1, (char *) key2); + int res = f->cmp(key1, key2); if (res) return res; key1 += len; @@ -2839,8 +2839,8 @@ String *Item_sum_udf_str::val_str(String *str) GROUP_CONCAT(DISTINCT expr,...) */ -int group_concat_key_cmp_with_distinct(void* arg, byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, + uchar* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*)arg; TABLE *table= grp_item->table; @@ -2865,7 +2865,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, int res; uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); - if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) + if ((res= field->cmp(key1 + offset, key2 + offset))) return res; } } @@ -2878,7 +2878,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, GROUP_CONCAT(expr,... ORDER BY col,... ) */ -int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) +int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; ORDER **order_item, **end; @@ -2904,7 +2904,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) int res; uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); - if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) + if ((res= field->cmp(key1 + offset, key2 + offset))) return (*order_item)->asc ? res : -res; } } @@ -2927,8 +2927,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) the duplicated values when inserting things sorted by ORDER BY */ -int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct_and_order(void* arg,uchar* key1, + uchar* key2) { if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) return 0; @@ -2940,7 +2940,7 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, Append data from current leaf to item->result */ -int dump_leaf_key(byte* key, element_count count __attribute__((unused)), +int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), Item_func_group_concat *item) { TABLE *table= item->table; @@ -2974,7 +2974,7 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); DBUG_ASSERT(offset < table->s->reclength); - res= field->val_str(&tmp, (char *) key + offset); + res= field->val_str(&tmp, key + offset); } else res= (*arg)->val_str(&tmp); @@ -3230,6 +3230,27 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) null_value= 1; max_length= thd->variables.group_concat_max_len; + uint32 offset; + if (separator->needs_conversion(separator->length(), separator->charset(), + collation.collation, &offset)) + { + uint32 buflen= collation.collation->mbmaxlen * separator->length(); + uint errors, conv_length; + char *buf; + String *new_separator; + + if (!(buf= (char*) thd->stmt_arena->alloc(buflen)) || + !(new_separator= new(thd->stmt_arena->mem_root) + String(buf, buflen, collation.collation))) + return TRUE; + + conv_length= copy_and_convert(buf, buflen, collation.collation, + separator->ptr(), separator->length(), + separator->charset(), &errors); + new_separator->length(conv_length); + separator= new_separator; + } + if (check_sum_func(thd, ref)) return TRUE; @@ -3290,14 +3311,20 @@ bool Item_func_group_concat::setup(THD *thd) tmp_table_param->force_copy_fields= force_copy_fields; DBUG_ASSERT(table == 0); /* + Currently we have to force conversion of BLOB values to VARCHAR's + if we are to store them in TREE objects used for ORDER BY and + DISTINCT. This leads to truncation if the BLOB's size exceeds + Field_varstring::MAX_SIZE. + */ + if (arg_count_order > 0 || distinct) + set_if_smaller(tmp_table_param->convert_blob_length, + Field_varstring::MAX_SIZE); + /* We have to create a temporary table to get descriptions of fields (types, sizes and so on). Note that in the table, we first have the ORDER BY fields, then the field list. - - We need to set set_sum_field in true for storing value of blob in buffer - of a record instead of a pointer of one. */ if (!(table= create_tmp_table(thd, tmp_table_param, all_fields, (ORDER*) 0, 0, TRUE, diff --git a/sql/item_sum.h b/sql/item_sum.h index 5cf4f93af0e..84b425755d1 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -361,7 +361,7 @@ public: Item *get_tmp_table_item(THD *thd); virtual Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); - bool walk(Item_processor processor, bool walk_subquery, byte *argument); + bool walk(Item_processor processor, bool walk_subquery, uchar *argument); bool init_sum_func_check(THD *thd); bool check_sum_func(THD *thd, Item **ref); bool register_sum_func(THD *thd, Item **ref); @@ -587,8 +587,8 @@ class Item_sum_count_distinct :public Item_sum_int bool always_null; // Set to 1 if the result is always NULL - friend int composite_key_cmp(void* arg, byte* key1, byte* key2); - friend int simple_str_key_cmp(void* arg, byte* key1, byte* key2); + friend int composite_key_cmp(void* arg, uchar* key1, uchar* key2); + friend int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2); public: Item_sum_count_distinct(List<Item> &list) @@ -1183,14 +1183,14 @@ class Item_func_group_concat : public Item_sum */ Item_func_group_concat *original; - friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1, - byte* key2); - friend int group_concat_key_cmp_with_order(void* arg, byte* key1, - byte* key2); + friend int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, + uchar* key2); + friend int group_concat_key_cmp_with_order(void* arg, uchar* key1, + uchar* key2); friend int group_concat_key_cmp_with_distinct_and_order(void* arg, - byte* key1, - byte* key2); - friend int dump_leaf_key(byte* key, + uchar* key1, + uchar* key2); + friend int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), Item_func_group_concat *group_concat_item); @@ -1243,6 +1243,6 @@ public: Item *copy_or_same(THD* thd); void no_rows_in_result() {} void print(String *str); - virtual bool change_context_processor(byte *cntx) + virtual bool change_context_processor(uchar *cntx) { context= (Name_resolution_context *)cntx; return FALSE; } }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 0fd57264784..95ff7dfd336 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -51,7 +51,7 @@ static bool make_datetime(date_time_format_types format, MYSQL_TIME *ltime, { char *buff; CHARSET_INFO *cs= &my_charset_bin; - uint length= 30; + uint length= MAX_DATE_STRING_REP_LENGTH; if (str->alloc(length)) return 1; @@ -886,9 +886,9 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, { i++; /* Change values[0...i-1] -> values[0...count-1] */ - bmove_upp((char*) (values+count), (char*) (values+i), + bmove_upp((uchar*) (values+count), (uchar*) (values+i), sizeof(*values)*i); - bzero((char*) values, sizeof(*values)*(count-i)); + bzero((uchar*) values, sizeof(*values)*(count-i)); break; } } @@ -1223,7 +1223,7 @@ bool get_interval_value(Item *args,interval_type int_type, ulonglong array[5]; longlong value; const char *str; - uint32 length; + size_t length; CHARSET_INFO *cs=str_value->charset(); LINT_INIT(value); @@ -1258,7 +1258,7 @@ bool get_interval_value(Item *args,interval_type int_type, interval->neg=1; str++; } - length=(uint32) (end-str); // Set up pointers to new str + length= (size_t) (end-str); // Set up pointers to new str } switch (int_type) { @@ -1379,7 +1379,7 @@ String *Item_date::val_str(String *str) MYSQL_TIME ltime; if (get_date(<ime, TIME_FUZZY_DATE)) return (String *) 0; - if (str->alloc(11)) + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; @@ -1428,7 +1428,7 @@ void Item_func_curdate::fix_length_and_dec() String *Item_func_curdate::val_str(String *str) { DBUG_ASSERT(fixed == 1); - if (str->alloc(11)) + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; @@ -1657,7 +1657,8 @@ String *Item_func_sec_to_time::val_str(String *str) MYSQL_TIME ltime; longlong arg_val= args[0]->val_int(); - if ((null_value=args[0]->null_value) || str->alloc(19)) + if ((null_value=args[0]->null_value) || + str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String*) 0; @@ -1842,6 +1843,10 @@ String *Item_func_date_format::val_str(String *str) size=max_length; else size=format_length(format); + + if (size < MAX_DATE_STRING_REP_LENGTH) + size= MAX_DATE_STRING_REP_LENGTH; + if (format == str) str= &value; // Save result here if (str->alloc(size)) @@ -1885,13 +1890,14 @@ String *Item_func_from_unixtime::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; - if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); + return str; } @@ -1940,14 +1946,15 @@ String *Item_func_convert_tz::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; - - if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) + + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } - + make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); + return str; } @@ -2058,27 +2065,6 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, uint fuzzy_date) if ((null_value= date_add_interval(ltime, int_type, interval))) return 1; - - /* Adjust cached_field_type according to the detected type. */ - if (cached_field_type == MYSQL_TYPE_STRING) - { - switch (ltime->time_type) - { - case MYSQL_TIMESTAMP_DATE: - cached_field_type= MYSQL_TYPE_DATE; - break; - case MYSQL_TIMESTAMP_DATETIME: - cached_field_type= MYSQL_TYPE_DATETIME; - break; - case MYSQL_TIMESTAMP_TIME: - cached_field_type= MYSQL_TYPE_TIME; - break; - default: - /* Shouldn't get here. */ - DBUG_ASSERT(0); - break; - } - } return 0; } @@ -2454,6 +2440,7 @@ String *Item_datetime_typecast::val_str(String *str) { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; + if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME, <ime, str)) @@ -2532,7 +2519,8 @@ String *Item_date_typecast::val_str(String *str) DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; - if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(11)) + if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && + !str->alloc(MAX_DATE_STRING_REP_LENGTH)) { make_date((DATE_TIME_FORMAT *) 0, <ime, str); return str; @@ -2585,7 +2573,7 @@ String *Item_func_makedate::val_str(String *str) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); - if (str->alloc(11)) + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) goto err; make_date((DATE_TIME_FORMAT *) 0, &l_time, str); return str; @@ -2721,6 +2709,7 @@ String *Item_func_add_time::val_str(String *str) days= (long)(seconds/86400L); calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds); + if (!is_time) { get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); @@ -2836,7 +2825,7 @@ String *Item_func_maketime::val_str(String *str) args[2]->null_value || minute < 0 || minute > 59 || second < 0 || second > 59 || - str->alloc(19)))) + str->alloc(MAX_DATE_STRING_REP_LENGTH)))) return 0; bzero((char *)<ime, sizeof(ltime)); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 992b79753ca..bd0954e6bdb 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -38,7 +38,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -53,7 +53,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -70,7 +70,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -86,7 +86,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -111,7 +111,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -144,7 +144,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -160,7 +160,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -176,7 +176,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -192,7 +192,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -208,7 +208,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -224,7 +224,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_yearweek :public Item_int_func @@ -239,7 +239,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -256,7 +256,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -286,7 +286,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_dayname :public Item_func_weekday @@ -319,7 +319,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -334,7 +334,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -585,7 +585,7 @@ public: Item_func_from_days(Item *a) :Item_date(a) {} const char *func_name() const { return "from_days"; } bool get_date(MYSQL_TIME *res, uint fuzzy_date); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -603,7 +603,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -617,7 +617,7 @@ class Item_func_from_unixtime :public Item_date_func const char *func_name() const { return "from_unixtime"; } void fix_length_and_dec(); bool get_date(MYSQL_TIME *res, uint fuzzy_date); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -676,7 +676,7 @@ public: } const char *func_name() const { return "sec_to_time"; } bool result_as_longlong() { return TRUE; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -698,7 +698,7 @@ public: bool get_date(MYSQL_TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -716,7 +716,7 @@ class Item_extract :public Item_int_func void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -753,7 +753,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -773,7 +773,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -884,7 +884,7 @@ public: max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -907,7 +907,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} double val_real() { return val_real_from_decimal(); } my_decimal *val_decimal(my_decimal *decimal_value) { @@ -949,7 +949,7 @@ public: :Item_str_timefunc(a, b ,c) {} String *val_str(String *str); const char *func_name() const { return "maketime"; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; class Item_func_microsecond :public Item_int_func @@ -963,7 +963,7 @@ public: decimals=0; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -981,7 +981,7 @@ public: maybe_null=1; } void print(String *str); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; @@ -1028,7 +1028,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 26474990644..f8457a1ae50 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -19,7 +19,7 @@ #include "mysql_priv.h" #include "my_xml.h" - +#include "sp_pcontext.h" /* TODO: future development directions: @@ -923,8 +923,8 @@ static Item *create_comparator(MY_XPATH *xpath, else if (a->type() == Item::XPATH_NODESET && b->type() == Item::XPATH_NODESET) { - uint len= context->end - context->beg; - set_if_bigger(len, 32); + uint len= xpath->query.end - context->beg; + set_if_smaller(len, 32); my_printf_error(ER_UNKNOWN_ERROR, "XPATH error: " "comparison of two nodesets is not supported: '%.*s'", @@ -2412,21 +2412,78 @@ my_xpath_parse_QName(MY_XPATH *xpath) } -/* +/** Scan Variable reference - SYNOPSYS + @details Implements parsing of two syntax structures: - [36] VariableReference ::= '$' QName - RETURN - 1 - success - 0 - failure + 1. Standard XPath syntax [36], for SP variables: + + VariableReference ::= '$' QName + + Finds a SP variable with the given name. + If outside of a SP context, or variable with + the given name doesn't exists, then error is returned. + + 2. Non-standard syntax - MySQL extension for user variables: + + VariableReference ::= '$' '@' QName + + Item, corresponding to the variable, is returned + in xpath->item in both cases. + + @param xpath pointer to XPath structure + + @return Operation status + @retval 1 Success + @retval 0 Failure */ + static int my_xpath_parse_VariableReference(MY_XPATH *xpath) { - return my_xpath_parse_term(xpath, MY_XPATH_LEX_DOLLAR) && - my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT); + LEX_STRING name; + int user_var; + const char *dollar_pos; + if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOLLAR) || + (!(dollar_pos= xpath->prevtok.beg)) || + (!((user_var= my_xpath_parse_term(xpath, MY_XPATH_LEX_AT) && + my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))) && + !my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))) + return 0; + + name.length= xpath->prevtok.end - xpath->prevtok.beg; + name.str= (char*) xpath->prevtok.beg; + + if (user_var) + xpath->item= new Item_func_get_user_var(name); + else + { + sp_variable_t *spv; + sp_pcontext *spc; + LEX *lex; + if ((lex= current_thd->lex) && + (spc= lex->spcont) && + (spv= spc->find_variable(&name))) + { + Item_splocal *splocal= new Item_splocal(name, spv->offset, spv->type, 0); +#ifndef DBUG_OFF + if (splocal) + splocal->m_sp= lex->sphead; +#endif + xpath->item= (Item*) splocal; + } + else + { + xpath->item= NULL; + DBUG_ASSERT(xpath->query.end > dollar_pos); + uint len= xpath->query.end - dollar_pos; + set_if_smaller(len, 32); + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", + MYF(0), len, dollar_pos); + } + } + return xpath->item ? 1 : 0; } @@ -2534,12 +2591,10 @@ void Item_xml_str_func::fix_length_and_dec() if (!rc) { - char context[32]; uint clen= xpath.query.end - xpath.lasttok.beg; - set_if_bigger(clen, sizeof(context) - 1); - strmake(context, xpath.lasttok.beg, clen); - my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%s'", - MYF(0), context); + set_if_smaller(clen, 32); + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", + MYF(0), clen, xpath.lasttok.beg); return; } @@ -2601,7 +2656,7 @@ static uint xml_parent_tag(MY_XML_NODE *items, uint nitems, uint level) RETURN Currently only MY_XML_OK */ -static int xml_enter(MY_XML_PARSER *st,const char *attr, uint len) +static int xml_enter(MY_XML_PARSER *st,const char *attr, size_t len) { MY_XML_USER_DATA *data= (MY_XML_USER_DATA*)st->user_data; MY_XML_NODE *nodes= (MY_XML_NODE*) data->pxml->ptr(); @@ -2632,7 +2687,7 @@ static int xml_enter(MY_XML_PARSER *st,const char *attr, uint len) RETURN Currently only MY_XML_OK */ -static int xml_value(MY_XML_PARSER *st,const char *attr, uint len) +static int xml_value(MY_XML_PARSER *st,const char *attr, size_t len) { MY_XML_USER_DATA *data= (MY_XML_USER_DATA*)st->user_data; MY_XML_NODE *nodes= (MY_XML_NODE*) data->pxml->ptr(); @@ -2662,7 +2717,7 @@ static int xml_value(MY_XML_PARSER *st,const char *attr, uint len) RETURN Currently only MY_XML_OK */ -static int xml_leave(MY_XML_PARSER *st,const char *attr, uint len) +static int xml_leave(MY_XML_PARSER *st,const char *attr, size_t len) { MY_XML_USER_DATA *data= (MY_XML_USER_DATA*)st->user_data; DBUG_ASSERT(data->level > 0); @@ -2712,7 +2767,7 @@ String *Item_xml_str_func::parse_xml(String *raw_xml, String *parsed_xml_buf) if ((rc= my_xml_parse(&p, raw_xml->ptr(), raw_xml->length())) != MY_XML_OK) { char buf[128]; - my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %d: %s", + my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %lu: %s", my_xml_error_lineno(&p) + 1, my_xml_error_pos(&p) + 1, my_xml_error_string(&p)); @@ -2768,6 +2823,16 @@ String *Item_func_xml_update::val_str(String *str) nodebeg+= fltbeg->num; + if (!nodebeg->level) + { + /* + Root element, without NameTest: + UpdateXML(xml, '/', 'replacement'); + Just return the replacement string. + */ + return rep; + } + tmp_value.length(0); tmp_value.set_charset(collation.collation); uint offs= nodebeg->type == MY_XML_NODE_TAG ? 1 : 0; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 9f2860ef403..650893fa7bd 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -41,7 +41,7 @@ public: Item_func_xml_extractvalue(Item *a,Item *b) :Item_xml_str_func(a,b) {} const char *func_name() const { return "extractvalue"; } String *val_str(String *); - bool check_partition_func_processor(byte *int_arg) {return FALSE;} + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} }; diff --git a/sql/key.cc b/sql/key.cc index 9a3155c459e..fee06ec058f 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -45,7 +45,7 @@ key_length is set to length of key before (not including) field */ -int find_ref_key(KEY *key, uint key_count, byte *record, Field *field, +int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, uint *key_length, uint *keypart) { reg2 int i; @@ -111,7 +111,8 @@ int find_ref_key(KEY *key, uint key_count, byte *record, Field *field, None */ -void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) +void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, + uint key_length) { uint length; KEY_PART_INFO *key_part; @@ -131,7 +132,7 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) Field_bit *field= (Field_bit *) (key_part->field); if (field->bit_len) { - uchar bits= get_rec_bits((uchar*) from_record + + uchar bits= get_rec_bits(from_record + key_part->null_offset + (key_part->null_bit == 128), field->bit_ofs, field->bit_len); @@ -144,7 +145,7 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) { key_length-= HA_KEY_BLOB_LENGTH; length= min(key_length, key_part->length); - key_part->field->get_key_image((char*) to_key, length, Field::itRAW); + key_part->field->get_key_image(to_key, length, Field::itRAW); to_key+= HA_KEY_BLOB_LENGTH; } else @@ -152,7 +153,7 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) length= min(key_length, key_part->length); Field *field= key_part->field; CHARSET_INFO *cs= field->charset(); - uint bytes= field->get_key_image((char*) to_key, length, Field::itRAW); + uint bytes= field->get_key_image(to_key, length, Field::itRAW); if (bytes < length) cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' '); } @@ -180,7 +181,7 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) None */ -void key_restore(byte *to_record, byte *from_key, KEY *key_info, +void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, uint key_length) { uint length; @@ -226,7 +227,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, from_key+= HA_KEY_BLOB_LENGTH; key_length-= HA_KEY_BLOB_LENGTH; field->set_ptr_offset(to_record - field->table->record[0], - (ulong) blob_length, (char*) from_key); + (ulong) blob_length, from_key); length= key_part->length; } else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) @@ -238,7 +239,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, key_length-= HA_KEY_BLOB_LENGTH; length= min(key_length, key_part->length); old_map= dbug_tmp_use_all_columns(field->table, field->table->write_set); - field->set_key_image((char *) from_key, length); + field->set_key_image(from_key, length); dbug_tmp_restore_column_map(field->table->write_set, old_map); from_key+= HA_KEY_BLOB_LENGTH; field->move_field_offset(-ptrdiff); @@ -275,11 +276,11 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, 1 Key has changed */ -bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length) +bool key_cmp_if_same(TABLE *table,const uchar *key,uint idx,uint key_length) { uint store_length; KEY_PART_INFO *key_part; - const byte *key_end= key + key_length;; + const uchar *key_end= key + key_length;; for (key_part=table->key_info[idx].key_part; key < key_end ; @@ -311,7 +312,7 @@ bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length) { CHARSET_INFO *cs= key_part->field->charset(); uint char_length= key_part->length / cs->mbmaxlen; - const byte *pos= table->record[0] + key_part->offset; + const uchar *pos= table->record[0] + key_part->offset; if (length > char_length) { char_length= my_charpos(cs, pos, pos + length, char_length); @@ -435,11 +436,11 @@ bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields) 1 Key is larger than range */ -int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length) +int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length) { uint store_length; - for (const byte *end=key + key_length; + for (const uchar *end=key + key_length; key < end; key+= store_length, key_part++) { @@ -462,7 +463,7 @@ int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length) key++; // Skip null byte store_length--; } - if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0) + if ((cmp=key_part->field->key_cmp(key, key_part->length)) < 0) return -1; if (cmp > 0) return 1; @@ -495,13 +496,13 @@ int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length) and return the result of the comparison. */ -int key_rec_cmp(void *key, byte *first_rec, byte *second_rec) +int key_rec_cmp(void *key, uchar *first_rec, uchar *second_rec) { KEY *key_info= (KEY*)key; uint key_parts= key_info->key_parts, i= 0; KEY_PART_INFO *key_part= key_info->key_part; - char *rec0= key_part->field->ptr - key_part->offset; - my_ptrdiff_t first_diff= first_rec - (byte*)rec0, sec_diff= second_rec - (byte*)rec0; + uchar *rec0= key_part->field->ptr - key_part->offset; + my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0; int result= 0; DBUG_ENTER("key_rec_cmp"); diff --git a/sql/lock.cc b/sql/lock.cc index ac6e90f68ff..08c109a17ab 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -137,7 +137,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); sql_lock=0; break; } @@ -145,7 +145,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); goto retry; } } @@ -161,7 +161,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, We do not wait for READ_ONLY=0, and fail. */ reset_lock_data(sql_lock); - my_free((gptr) sql_lock, MYF(0)); + my_free((uchar*) sql_lock, MYF(0)); sql_lock=0; my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); break; @@ -173,7 +173,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); sql_lock=0; break; } @@ -191,12 +191,19 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, if (rc > 1) /* a timeout or a deadlock */ { my_error(rc, MYF(0)); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); sql_lock= 0; break; } else if (rc == 1) /* aborted */ { + /* + reset_lock_data is required here. If thr_multi_lock fails it + resets lock type for tables, which were locked before (and + including) one that caused error. Lock type for other tables + preserved. + */ + reset_lock_data(sql_lock); thd->some_tables_deleted=1; // Try again sql_lock->lock_count= 0; // Locks are already freed } @@ -285,7 +292,7 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) thr_multi_unlock(sql_lock->locks,sql_lock->lock_count); if (sql_lock->table_count) VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count)); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); DBUG_VOID_RETURN; } @@ -435,7 +442,7 @@ void mysql_lock_downgrade_write(THD *thd, TABLE *table, { for (uint i=0; i < locked->lock_count; i++) thr_downgrade_write_lock(locked->locks[i], new_lock_type); - my_free((gptr) locked,MYF(0)); + my_free((uchar*) locked,MYF(0)); } } @@ -453,7 +460,7 @@ void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock) { for (uint i=0; i < locked->lock_count; i++) thr_abort_locks(locked->locks[i]->lock, upgrade_lock); - my_free((gptr) locked,MYF(0)); + my_free((uchar*) locked,MYF(0)); } DBUG_VOID_RETURN; } @@ -488,7 +495,7 @@ bool mysql_lock_abort_for_thread(THD *thd, TABLE *table) table->in_use->thread_id)) result= TRUE; } - my_free((gptr) locked,MYF(0)); + my_free((uchar*) locked,MYF(0)); } DBUG_RETURN(result); } @@ -530,8 +537,8 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b) } /* Delete old, not needed locks */ - my_free((gptr) a,MYF(0)); - my_free((gptr) b,MYF(0)); + my_free((uchar*) a,MYF(0)); + my_free((uchar*) b,MYF(0)); DBUG_RETURN(sql_lock); } @@ -749,7 +756,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, /* Clear the lock type of the lock data that are stored already. */ sql_lock->lock_count= locks - sql_lock->locks; reset_lock_data(sql_lock); - my_free((gptr) sql_lock,MYF(0)); + my_free((uchar*) sql_lock,MYF(0)); DBUG_RETURN(0); } } @@ -904,10 +911,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use) if (check_in_use) { /* Only insert the table if we haven't insert it already */ - for (table=(TABLE*) hash_first(&open_cache, (byte*)key, + for (table=(TABLE*) hash_first(&open_cache, (uchar*)key, key_length, &state); table ; - table = (TABLE*) hash_next(&open_cache,(byte*) key, + table = (TABLE*) hash_next(&open_cache,(uchar*) key, key_length, &state)) { if (table->in_use == thd) @@ -935,7 +942,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list) { if (table_list->table) { - hash_delete(&open_cache, (byte*) table_list->table); + hash_delete(&open_cache, (uchar*) table_list->table); broadcast_refresh(); } } diff --git a/sql/log.cc b/sql/log.cc index 9e9cd35ec9a..6dc204265b0 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -296,6 +296,8 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type) table->db= log_thd->db; table->db_length= log_thd->db_length; + lex_start(log_thd); + log_thd->clear_error(); if (simple_open_n_lock_tables(log_thd, table) || table->table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || table->table->file->ha_rnd_init(0)) @@ -305,6 +307,9 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type) table->table->use_all_columns(); table->table->locked_by_logger= TRUE; table->table->no_replicate= TRUE; + + /* Honor next number columns if present */ + table->table->next_number_field= table->table->found_next_number_field; } /* restore thread settings */ if (curr) @@ -438,6 +443,7 @@ bool Log_to_csv_event_handler:: CHARSET_INFO *client_cs) { TABLE *table= general_log.table; + uint field_index; /* "INSERT INTO general_log" can generate warning sometimes. @@ -488,6 +494,12 @@ bool Log_to_csv_event_handler:: table->field[4]->set_notnull(); table->field[5]->set_notnull(); + /* Set any extra columns to their default values */ + for (field_index= 6 ; field_index < table->s->fields ; field_index++) + { + table->field[field_index]->set_default(); + } + /* log table entries are not replicated at the moment */ tmp_disable_binlog(current_thd); @@ -1329,6 +1341,7 @@ void Log_to_csv_event_handler:: /* close the table */ log_thd->store_globals(); table->table->file->ha_rnd_end(); + table->table->file->ha_release_auto_increment(); /* discard logger mark before unlock*/ table->table->locked_by_logger= FALSE; close_thread_tables(log_thd, lock_in_use); @@ -1435,7 +1448,7 @@ static int binlog_close_connection(handlerton *hton, THD *thd) DBUG_ASSERT(mysql_bin_log.is_open() && trx_data->empty()); thd->ha_data[binlog_hton->slot]= 0; trx_data->~binlog_trx_data(); - my_free((gptr)trx_data, MYF(0)); + my_free((uchar*)trx_data, MYF(0)); return 0; } @@ -1670,7 +1683,7 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg) char magic[4]; DBUG_ASSERT(my_b_tell(log) == 0); - if (my_b_read(log, (byte*) magic, sizeof(magic))) + if (my_b_read(log, (uchar*) magic, sizeof(magic))) { *errmsg = "I/O error reading the header from the binary log"; sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno, @@ -1772,15 +1785,16 @@ static int find_uniq_filename(char *name) struct st_my_dir *dir_info; reg1 struct fileinfo *file_info; ulong max_found=0; - + size_t buf_length, length; + char *start, *end; DBUG_ENTER("find_uniq_filename"); - uint length = dirname_part(buff,name); - char *start = name + length; - char *end = strend(start); + length= dirname_part(buff, name, &buf_length); + start= name + length; + end= strend(start); *end='.'; - length= (uint) (end-start+1); + length= (size_t) (end-start+1); if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT)))) { // This shouldn't happen @@ -1790,7 +1804,7 @@ static int find_uniq_filename(char *name) file_info= dir_info->dir_entry; for (i=dir_info->number_off_files ; i-- ; file_info++) { - if (bcmp(file_info->name,start,length) == 0 && + if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 && test_if_number(file_info->name+length, &number,0)) { set_if_bigger(max_found,(ulong) number); @@ -1894,7 +1908,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, ); end= strnmov(buff + len, "Time Id Command Argument\n", sizeof(buff) - len); - if (my_b_write(&log_file, (byte*) buff, (uint) (end-buff)) || + if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) || flush_io_cache(&log_file)) goto err; } @@ -2102,30 +2116,30 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, start.tm_mday, start.tm_hour, start.tm_min, start.tm_sec); - if (my_b_write(&log_file, (byte*) &time_buff, time_buff_len)) + if (my_b_write(&log_file, (uchar*) &time_buff, time_buff_len)) goto err; } else - if (my_b_write(&log_file, (byte*) "\t\t" ,2) < 0) + if (my_b_write(&log_file, (uchar*) "\t\t" ,2) < 0) goto err; /* command_type, thread_id */ length= my_snprintf(buff, 32, "%5ld ", (long) thread_id); - if (my_b_write(&log_file, (byte*) buff, length)) + if (my_b_write(&log_file, (uchar*) buff, length)) goto err; - if (my_b_write(&log_file, (byte*) command_type, command_type_len)) + if (my_b_write(&log_file, (uchar*) command_type, command_type_len)) goto err; - if (my_b_write(&log_file, (byte*) "\t", 1)) + if (my_b_write(&log_file, (uchar*) "\t", 1)) goto err; /* sql_text */ - if (my_b_write(&log_file, (byte*) sql_text, sql_text_len)) + if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len)) goto err; - if (my_b_write(&log_file, (byte*) "\n", 1) || + if (my_b_write(&log_file, (uchar*) "\n", 1) || flush_io_cache(&log_file)) goto err; } @@ -2205,7 +2219,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, start.tm_min, start.tm_sec); /* Note that my_b_write() assumes it knows the length for this */ - if (my_b_write(&log_file, (byte*) buff, buff_len)) + if (my_b_write(&log_file, (uchar*) buff, buff_len)) tmp_errno= errno; } if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1) @@ -2213,7 +2227,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, tmp_errno= errno; if (my_b_printf(&log_file, user_host, user_host_len) != user_host_len) tmp_errno= errno; - if (my_b_write(&log_file, (byte*) "\n", 1)) + if (my_b_write(&log_file, (uchar*) "\n", 1)) tmp_errno= errno; } /* For slow query log */ @@ -2261,18 +2275,18 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, { *end++=';'; *end='\n'; - if (my_b_write(&log_file, (byte*) "SET ", 4) || - my_b_write(&log_file, (byte*) buff + 1, (uint) (end-buff))) + if (my_b_write(&log_file, (uchar*) "SET ", 4) || + my_b_write(&log_file, (uchar*) buff + 1, (uint) (end-buff))) tmp_errno= errno; } if (is_command) { end= strxmov(buff, "# administrator command: ", NullS); buff_len= (ulong) (end - buff); - my_b_write(&log_file, (byte*) buff, buff_len); + my_b_write(&log_file, (uchar*) buff, buff_len); } - if (my_b_write(&log_file, (byte*) sql_text, sql_text_len) || - my_b_write(&log_file, (byte*) ";\n",2) || + if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len) || + my_b_write(&log_file, (uchar*) ";\n",2) || flush_io_cache(&log_file)) tmp_errno= errno; if (tmp_errno) @@ -2456,7 +2470,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, an extension for the binary log files. In this case we write a standard header to it. */ - if (my_b_safe_write(&log_file, (byte*) BINLOG_MAGIC, + if (my_b_safe_write(&log_file, (uchar*) BINLOG_MAGIC, BIN_LOG_HEADER_SIZE)) goto err; bytes_written+= BIN_LOG_HEADER_SIZE; @@ -2528,9 +2542,9 @@ bool MYSQL_BIN_LOG::open(const char *log_name, As this is a new log file, we write the file name to the index file. As every time we write to the index file, we sync it. */ - if (my_b_write(&index_file, (byte*) log_file_name, + if (my_b_write(&index_file, (uchar*) log_file_name, strlen(log_file_name)) || - my_b_write(&index_file, (byte*) "\n", 1) || + my_b_write(&index_file, (uchar*) "\n", 1) || flush_io_cache(&index_file) || my_sync(index_file.file, MYF(MY_WME))) goto err; @@ -2598,7 +2612,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset) int bytes_read; my_off_t init_offset= offset; File file= index_file->file; - byte io_buf[IO_SIZE*2]; + uchar io_buf[IO_SIZE*2]; DBUG_ENTER("copy_up_file_and_fill"); for (;; offset+= bytes_read) @@ -2610,7 +2624,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset) if (!bytes_read) break; // end of file (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0)); - if (my_write(file, (byte*) io_buf, bytes_read, MYF(MY_WME | MY_NABP))) + if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP))) goto err; } /* The following will either truncate the file or fill the end with \n' */ @@ -2822,7 +2836,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) need_start_event=1; if (!open_index_file(index_file_name, 0)) open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0); - my_free((gptr) save_name, MYF(0)); + my_free((uchar*) save_name, MYF(0)); err: VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -3324,7 +3338,7 @@ bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) safe_mutex_assert_owner(&LOCK_log); do { - if (my_b_append(&log_file,(byte*) buf,len)) + if (my_b_append(&log_file,(uchar*) buf,len)) { error= 1; goto err; @@ -3398,7 +3412,7 @@ int THD::binlog_setup_trx_data() open_cached_file(&trx_data->trans_log, mysql_tmpdir, LOG_PREFIX, binlog_cache_size, MYF(MY_WME))) { - my_free((gptr)trx_data, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR)); ha_data[binlog_hton->slot]= 0; DBUG_RETURN(1); // Didn't manage to set it up } @@ -3804,7 +3818,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) for (uint i= 0; i < thd->user_var_events.elements; i++) { BINLOG_USER_VAR_EVENT *user_var_event; - get_dynamic(&thd->user_var_events,(gptr) &user_var_event, i); + get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i); User_var_log_event e(thd, user_var_event->user_var_event->name.str, user_var_event->user_var_event->name.length, user_var_event->value, @@ -4131,8 +4145,16 @@ void MYSQL_BIN_LOG::close(uint exiting) if (log_file.type == WRITE_CACHE && log_type == LOG_BIN) { my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET; - byte flags=0; // clearing LOG_EVENT_BINLOG_IN_USE_F + my_off_t org_position= my_tell(log_file.file, MYF(0)); + uchar flags= 0; // clearing LOG_EVENT_BINLOG_IN_USE_F my_pwrite(log_file.file, &flags, 1, offset, MYF(0)); + /* + Restore position so that anything we have in the IO_cache is written + to the correct position. + We need the seek here, as my_pwrite() is not guaranteed to keep the + original position on system that doesn't support pwrite(). + */ + my_seek(log_file.file, org_position, MY_SEEK_SET, MYF(0)); } /* this will cleanup IO_CACHE, sync and close the file */ @@ -4256,17 +4278,21 @@ bool flush_error_log() (void) my_delete(err_temp, MYF(0)); if (freopen(err_temp,"a+",stdout)) { + int fd; + size_t bytes; + uchar buf[IO_SIZE]; + freopen(err_temp,"a+",stderr); (void) my_delete(err_renamed, MYF(0)); my_rename(log_error_file,err_renamed,MYF(0)); if (freopen(log_error_file,"a+",stdout)) freopen(log_error_file,"a+",stderr); - int fd, bytes; - char buf[IO_SIZE]; + if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0) { - while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0) - my_fwrite(stderr, (byte*) buf, bytes, MYF(0)); + while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) && + bytes != MY_FILE_ERROR) + my_fwrite(stderr, buf, bytes, MYF(0)); my_close(fd, MYF(0)); } (void) my_delete(err_temp, MYF(0)); @@ -4840,9 +4866,9 @@ void TC_LOG_MMAP::close() pthread_cond_destroy(&pages[i].cond); } case 3: - my_free((gptr)pages, MYF(0)); + my_free((uchar*)pages, MYF(0)); case 2: - my_munmap((byte*)data, (size_t)file_length); + my_munmap((char*)data, (size_t)file_length); case 1: my_close(fd, MYF(0)); } @@ -4876,13 +4902,13 @@ int TC_LOG_MMAP::recover() } if (hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0, - sizeof(my_xid), 0, 0, MYF(0))) + sizeof(my_xid), 0, 0, MYF(0))) goto err1; for ( ; p < end_p ; p++) { for (my_xid *x=p->start; x < p->end; x++) - if (*x && my_hash_insert(&xids, (byte *)x)) + if (*x && my_hash_insert(&xids, (uchar *)x)) goto err2; // OOM } @@ -5075,7 +5101,7 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) if (! fdle->is_valid() || hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0, - sizeof(my_xid), 0, 0, MYF(0))) + sizeof(my_xid), 0, 0, MYF(0))) goto err1; init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE); @@ -5087,8 +5113,8 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) if (ev->get_type_code() == XID_EVENT) { Xid_log_event *xev=(Xid_log_event *)ev; - byte *x=(byte *)memdup_root(&mem_root, (char *)& xev->xid, - sizeof(xev->xid)); + uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid, + sizeof(xev->xid)); if (! x) goto err2; my_hash_insert(&xids, x); diff --git a/sql/log_event.cc b/sql/log_event.cc index 1241d0b02ed..658f33e7bed 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -146,12 +146,11 @@ static void pretty_print_str(IO_CACHE* cache, char* str, int len) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static void clear_all_errors(THD *thd, struct st_relay_log_info *rli) +static void clear_all_errors(THD *thd, RELAY_LOG_INFO *rli) { thd->query_error = 0; thd->clear_error(); - *rli->last_slave_error = 0; - rli->last_slave_errno = 0; + rli->clear_error(); } @@ -299,10 +298,10 @@ static void cleanup_load_tmpdir() static bool write_str(IO_CACHE *file, char *str, uint length) { - byte tmp[1]; - tmp[0]= (byte) length; + uchar tmp[1]; + tmp[0]= (uchar) length; return (my_b_safe_write(file, tmp, sizeof(tmp)) || - my_b_safe_write(file, (byte*) str, length)); + my_b_safe_write(file, (uchar*) str, length)); } @@ -310,8 +309,8 @@ static bool write_str(IO_CACHE *file, char *str, uint length) read_str() */ -static inline int read_str(const char **buf, const char *buf_end, const char **str, - uint8 *len) +static inline int read_str(const char **buf, const char *buf_end, + const char **str, uint8 *len) { if (*buf + ((uint) (uchar) **buf) >= buf_end) return 1; @@ -637,7 +636,7 @@ void Log_event::init_show_field_list(List<Item>* field_list) bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) { - byte header[LOG_EVENT_HEADER_LEN]; + uchar header[LOG_EVENT_HEADER_LEN]; DBUG_ENTER("Log_event::write_header"); /* Store number of bytes that will be written by this event */ @@ -724,7 +723,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, if (log_lock) pthread_mutex_lock(log_lock); - if (my_b_read(file, (byte*) buf, sizeof(buf))) + if (my_b_read(file, (uchar*) buf, sizeof(buf))) { /* If the read hits eof, we must report it as eof so the caller @@ -825,7 +824,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, LOCK_MUTEX; DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file))); - if (my_b_read(file, (byte *) head, header_size)) + if (my_b_read(file, (uchar *) head, header_size)) { DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \ failed my_b_read")); @@ -859,14 +858,14 @@ failed my_b_read")); } // some events use the extra byte to null-terminate strings - if (!(buf = my_malloc(data_len+1, MYF(MY_WME)))) + if (!(buf = (char*) my_malloc(data_len+1, MYF(MY_WME)))) { error = "Out of memory"; goto err; } buf[data_len] = 0; memcpy(buf, head, header_size); - if (my_b_read(file, (byte*) buf + header_size, data_len - header_size)) + if (my_b_read(file, (uchar*) buf + header_size, data_len - header_size)) { error = "read error"; goto err; @@ -911,16 +910,15 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, DBUG_ENTER("Log_event::read_log_event(char*,...)"); DBUG_ASSERT(description_event != 0); DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version)); + /* Check the integrity */ if (event_len < EVENT_LEN_OFFSET || + buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT || (uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET)) { *error="Sanity check failed"; // Needed to free buffer DBUG_RETURN(NULL); // general sanity check - will fail on a partial read } - /* To check the integrity of the Log_event_type enumeration */ - DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] < ENUM_END_EVENT); - switch(buf[EVENT_TYPE_OFFSET]) { case QUERY_EVENT: ev = new Query_log_event(buf, event_len, description_event, QUERY_EVENT); @@ -1092,8 +1090,8 @@ void Log_event::print_header(IO_CACHE* file, ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); DBUG_ASSERT(bytes_written >= 0); - DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf)); - my_b_write(file, (byte*) emit_buf, bytes_written); + DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); + my_b_write(file, (uchar*) emit_buf, bytes_written); ptr += LOG_EVENT_MINIMAL_HEADER_LEN; hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN; } @@ -1123,8 +1121,8 @@ void Log_event::print_header(IO_CACHE* file, (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); DBUG_ASSERT(bytes_written >= 0); - DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf)); - my_b_write(file, (byte*) emit_buf, bytes_written); + DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); + my_b_write(file, (uchar*) emit_buf, bytes_written); hex_string[0]= 0; char_string[0]= 0; c= char_string; @@ -1144,14 +1142,14 @@ void Log_event::print_header(IO_CACHE* file, (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); DBUG_ASSERT(bytes_written >= 0); - DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf)); - my_b_write(file, (byte*) emit_buf, bytes_written); + DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); + my_b_write(file, (uchar*) emit_buf, bytes_written); } /* need a # to prefix the rest of printouts for example those of Rows_log_event::print_helper(). */ - my_b_write(file, reinterpret_cast<const byte*>("# "), 2); + my_b_write(file, reinterpret_cast<const uchar*>("# "), 2); } DBUG_VOID_RETURN; } @@ -1239,7 +1237,7 @@ void Query_log_event::pack_info(Protocol *protocol) { // TODO: show the catalog ?? char *buf, *pos; - if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME)))) + if (!(buf= (char*) my_malloc(9 + db_len + q_len, MYF(MY_WME)))) return; pos= buf; if (!(flags & LOG_EVENT_SUPPRESS_USE_F) @@ -1440,12 +1438,12 @@ bool Query_log_event::write(IO_CACHE* file) event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len; return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) || + my_b_safe_write(file, (uchar*) buf, QUERY_HEADER_LEN) || write_post_header_for_derived(file) || - my_b_safe_write(file, (byte*) start_of_status, + my_b_safe_write(file, (uchar*) start_of_status, (uint) (start-start_of_status)) || - my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) || - my_b_safe_write(file, (byte*) query, q_len)) ? 1 : 0; + my_b_safe_write(file, (db) ? (uchar*) db : (uchar*)"", db_len + 1) || + my_b_safe_write(file, (uchar*) query, q_len)) ? 1 : 0; } /* @@ -1462,20 +1460,31 @@ Query_log_event::Query_log_event() /* - Query_log_event::Query_log_event() + SYNOPSIS + Query_log_event::Query_log_event() + thd - thread handle + query_arg - array of char representing the query + query_length - size of the `query_arg' array + using_trans - there is a modified transactional table + suppress_use - suppress the generation of 'USE' statements + killed_status_arg - an optional with default to THD::KILLED_NO_VALUE + if the value is different from the default, the arg + is set to the current thd->killed value. + A caller might need to masquerade thd->killed with + THD::NOT_KILLED. + DESCRIPTION + Creates an event for binlogging + The value for local `killed_status' can be supplied by caller. */ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, - bool suppress_use) + bool suppress_use, THD::killed_state killed_status_arg) :Log_event(thd_arg, ((thd_arg->tmp_table_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) | (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0)), using_trans), data_buf(0), query(query_arg), catalog(thd_arg->catalog), db(thd_arg->db), q_len((uint32) query_length), - error_code((thd_arg->killed != THD::NOT_KILLED) ? - ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? - 0 : thd->killed_errno()) : thd_arg->net.last_errno), thread_id(thd_arg->thread_id), /* save the original thread id; we already know the server id */ slave_proxy_id(thd_arg->variables.pseudo_thread_id), @@ -1487,6 +1496,14 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, charset_database_number(0) { time_t end_time; + + if (killed_status_arg == THD::KILLED_NO_VALUE) + killed_status_arg= thd_arg->killed; + error_code= + (killed_status_arg == THD::NOT_KILLED) ? thd_arg->net.last_errno : + ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 : + thd->killed_errno()); + time(&end_time); exec_time = (ulong) (end_time - thd->start_time); catalog_len = (catalog) ? (uint32) strlen(catalog) : 0; @@ -1559,7 +1576,8 @@ static void copy_str_and_move(const char **src, */ Query_log_event::Query_log_event(const char* buf, uint event_len, - const Format_description_log_event *description_event, + const Format_description_log_event + *description_event, Log_event_type event_type) :Log_event(buf, description_event), data_buf(0), query(NullS), db(NullS), catalog_len(0), status_vars_len(0), @@ -1752,7 +1770,7 @@ void Query_log_event::print_query_header(IO_CACHE* file, end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); end= strmov(end, print_event_info->delimiter); *end++='\n'; - my_b_write(file, (byte*) buff, (uint) (end-buff)); + my_b_write(file, (uchar*) buff, (uint) (end-buff)); if (flags & LOG_EVENT_THREAD_SPECIFIC_F) my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n", (ulong)thread_id, print_event_info->delimiter); @@ -1836,7 +1854,7 @@ void Query_log_event::print_query_header(IO_CACHE* file, print_event_info->charset_inited= 1; print_event_info->charset[0]= ~charset[0]; // force a difference to force write } - if (unlikely(bcmp(print_event_info->charset, charset, 6))) + if (unlikely(bcmp((uchar*) print_event_info->charset, (uchar*) charset, 6))) { CHARSET_INFO *cs_info= get_charset(uint2korr(charset), MYF(MY_WME)); if (cs_info) @@ -1859,7 +1877,8 @@ void Query_log_event::print_query_header(IO_CACHE* file, } if (time_zone_len) { - if (bcmp(print_event_info->time_zone_str, time_zone_str, time_zone_len+1)) + if (bcmp((uchar*) print_event_info->time_zone_str, + (uchar*) time_zone_str, time_zone_len+1)) { my_b_printf(file,"SET @@session.time_zone='%s'%s\n", time_zone_str, print_event_info->delimiter); @@ -1890,7 +1909,7 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) Write_on_release_cache cache(&print_event_info->head_cache, file); print_query_header(&cache, print_event_info); - my_b_write(&cache, (byte*) query, q_len); + my_b_write(&cache, (uchar*) query, q_len); my_b_printf(&cache, "%s\n", print_event_info->delimiter); } #endif /* MYSQL_CLIENT */ @@ -2070,7 +2089,7 @@ int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli, clear_all_errors(thd, const_cast<RELAY_LOG_INFO*>(rli)); /* Can ignore query */ else { - slave_print_msg(ERROR_LEVEL, rli, expected_error, + rli->report(ERROR_LEVEL, expected_error, "\ Query partially completed on the master (error on master: %d) \ and was aborted. There is a chance that your master is inconsistent at this \ @@ -2099,7 +2118,7 @@ compare_errors: !ignored_error_code(actual_error) && !ignored_error_code(expected_error)) { - slave_print_msg(ERROR_LEVEL, rli, 0, + rli->report(ERROR_LEVEL, 0, "\ Query caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ @@ -2125,7 +2144,7 @@ Default database: '%s'. Query: '%s'", */ else if (thd->query_error || thd->is_fatal_error) { - slave_print_msg(ERROR_LEVEL, rli, actual_error, + rli->report(ERROR_LEVEL, actual_error, "Error '%s' on query. Default database: '%s'. Query: '%s'", (actual_error ? thd->net.last_error : "unexpected success or fatal error"), @@ -2327,7 +2346,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN); int4store(buff + ST_CREATED_OFFSET,created); return (write_header(file, sizeof(buff)) || - my_b_safe_write(file, (byte*) buff, sizeof(buff))); + my_b_safe_write(file, (uchar*) buff, sizeof(buff))); } #endif @@ -2562,7 +2581,7 @@ Format_description_log_event(const char* buf, DBUG_PRINT("info", ("common_header_len=%d number_of_event_types=%d", common_header_len, number_of_event_types)); /* If alloc fails, we'll detect it in is_valid() */ - post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1, + post_header_len= (uint8*) my_memdup((uchar*)buf+ST_COMMON_HEADER_LEN_OFFSET+1, number_of_event_types* sizeof(*post_header_len), MYF(0)); calc_server_version_split(); @@ -2576,12 +2595,12 @@ bool Format_description_log_event::write(IO_CACHE* file) We don't call Start_log_event_v3::write() because this would make 2 my_b_safe_write(). */ - byte buff[FORMAT_DESCRIPTION_HEADER_LEN]; + uchar buff[FORMAT_DESCRIPTION_HEADER_LEN]; int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version); memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN); int4store(buff + ST_CREATED_OFFSET,created); buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN; - memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET+1, (byte*) post_header_len, + memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET+1, (uchar*) post_header_len, LOG_EVENT_TYPES); return (write_header(file, sizeof(buff)) || my_b_safe_write(file, buff, sizeof(buff))); @@ -2608,11 +2627,11 @@ int Format_description_log_event::do_apply_event(RELAY_LOG_INFO const *rli) if (!artificial_event && created && thd->transaction.all.nht) { /* This is not an error (XA is safe), just an information */ - slave_print_msg(INFORMATION_LEVEL, rli, 0, - "Rolling back unfinished transaction (no COMMIT " - "or ROLLBACK in relay log). A probable cause is that " - "the master died while writing the transaction to " - "its binary log, thus rolled back too."); + rli->report(INFORMATION_LEVEL, 0, + "Rolling back unfinished transaction (no COMMIT " + "or ROLLBACK in relay log). A probable cause is that " + "the master died while writing the transaction to " + "its binary log, thus rolled back too."); const_cast<RELAY_LOG_INFO*>(rli)->cleanup_context(thd, 1); } #endif @@ -2836,7 +2855,7 @@ void Load_log_event::pack_info(Protocol *protocol) { char *buf, *end; - if (!(buf= my_malloc(get_query_buffer_length(), MYF(MY_WME)))) + if (!(buf= (char*) my_malloc(get_query_buffer_length(), MYF(MY_WME)))) return; print_query(TRUE, buf, &end, 0, 0); protocol->store(buf, end-buf, &my_charset_bin); @@ -2860,7 +2879,7 @@ bool Load_log_event::write_data_header(IO_CACHE* file) buf[L_TBL_LEN_OFFSET] = (char)table_name_len; buf[L_DB_LEN_OFFSET] = (char)db_len; int4store(buf + L_NUM_FIELDS_OFFSET, num_fields); - return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN) != 0; + return my_b_safe_write(file, (uchar*)buf, LOAD_HEADER_LEN) != 0; } @@ -2874,13 +2893,13 @@ bool Load_log_event::write_data_body(IO_CACHE* file) return 1; if (num_fields && fields && field_lens) { - if (my_b_safe_write(file, (byte*)field_lens, num_fields) || - my_b_safe_write(file, (byte*)fields, field_block_len)) + if (my_b_safe_write(file, (uchar*)field_lens, num_fields) || + my_b_safe_write(file, (uchar*)fields, field_block_len)) return 1; } - return (my_b_safe_write(file, (byte*)table_name, table_name_len + 1) || - my_b_safe_write(file, (byte*)db, db_len + 1) || - my_b_safe_write(file, (byte*)fname, fname_len)); + return (my_b_safe_write(file, (uchar*)table_name, table_name_len + 1) || + my_b_safe_write(file, (uchar*)db, db_len + 1) || + my_b_safe_write(file, (uchar*)fname, fname_len)); } @@ -3430,6 +3449,10 @@ error: thd->query_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); + + DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", + thd->query_error= 0; thd->is_fatal_error= 1;); + if (thd->query_error) { /* this err/sql_errno code is copy-paste from net_send_error() */ @@ -3442,19 +3465,25 @@ error: sql_errno=ER_UNKNOWN_ERROR; err=ER(sql_errno); } - slave_print_msg(ERROR_LEVEL, rli, sql_errno,"\ + rli->report(ERROR_LEVEL, sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", err, (char*)table_name, print_slave_db_safe(remember_db)); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); - + if (thd->is_fatal_error) { - slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR, "\ -Fatal error running LOAD DATA INFILE on table '%s'. Default database: '%s'", - (char*)table_name, print_slave_db_safe(remember_db)); + char buf[256]; + my_snprintf(buf, sizeof(buf), + "Running LOAD DATA INFILE on table '%-.64s'." + " Default database: '%-.64s'", + (char*)table_name, + print_slave_db_safe(remember_db)); + + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), buf); return 1; } @@ -3501,7 +3530,7 @@ void Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) print_header(&cache, print_event_info, FALSE); my_b_printf(&cache, "\tRotate to "); if (new_log_ident) - my_b_write(&cache, (byte*) new_log_ident, (uint)ident_len); + my_b_write(&cache, (uchar*) new_log_ident, (uint)ident_len); my_b_printf(&cache, " pos: %s\n", llstr(pos, buf)); } #endif /* MYSQL_CLIENT */ @@ -3567,8 +3596,8 @@ bool Rotate_log_event::write(IO_CACHE* file) char buf[ROTATE_HEADER_LEN]; int8store(buf + R_POS_OFFSET, pos); return (write_header(file, ROTATE_HEADER_LEN + ident_len) || - my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || - my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); + my_b_safe_write(file, (uchar*)buf, ROTATE_HEADER_LEN) || + my_b_safe_write(file, (uchar*)new_log_ident, (uint) ident_len)); } #endif @@ -3735,8 +3764,8 @@ const char* Intvar_log_event::get_var_type_name() #ifndef MYSQL_CLIENT bool Intvar_log_event::write(IO_CACHE* file) { - byte buf[9]; - buf[I_TYPE_OFFSET]= (byte) type; + uchar buf[9]; + buf[I_TYPE_OFFSET]= (uchar) type; int8store(buf + I_VAL_OFFSET, val); return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); @@ -3864,7 +3893,7 @@ Rand_log_event::Rand_log_event(const char* buf, #ifndef MYSQL_CLIENT bool Rand_log_event::write(IO_CACHE* file) { - byte buf[16]; + uchar buf[16]; int8store(buf + RAND_SEED1_OFFSET, seed1); int8store(buf + RAND_SEED2_OFFSET, seed2); return (write_header(file, sizeof(buf)) || @@ -3971,7 +4000,7 @@ Xid_log_event(const char* buf, bool Xid_log_event::write(IO_CACHE* file) { return write_header(file, sizeof(xid)) || - my_b_safe_write(file, (byte*) &xid, sizeof(xid)); + my_b_safe_write(file, (uchar*) &xid, sizeof(xid)); } #endif @@ -4019,7 +4048,8 @@ void User_var_log_event::pack_info(Protocol* protocol) if (is_null) { - buf= my_malloc(val_offset + 5, MYF(MY_WME)); + if (!(buf= (char*) my_malloc(val_offset + 5, MYF(MY_WME)))) + return; strmov(buf + val_offset, "NULL"); event_len= val_offset + 4; } @@ -4029,28 +4059,37 @@ void User_var_log_event::pack_info(Protocol* protocol) case REAL_RESULT: double real_val; float8get(real_val, val); - buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME)); + if (!(buf= (char*) my_malloc(val_offset + FLOATING_POINT_BUFFER, + MYF(MY_WME)))) + return; event_len+= my_sprintf(buf + val_offset, (buf + val_offset, "%.14g", real_val)); break; case INT_RESULT: - buf= my_malloc(val_offset + 22, MYF(MY_WME)); + if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME)))) + return; event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf; break; case DECIMAL_RESULT: { - buf= my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH, MYF(MY_WME)); + if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH, + MYF(MY_WME)))) + return; String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH, &my_charset_bin); my_decimal dec; - binary2my_decimal(E_DEC_FATAL_ERROR, val+2, &dec, val[0], val[1]); + binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0], + val[1]); my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str); event_len= str.length() + val_offset; break; } case STRING_RESULT: /* 15 is for 'COLLATE' and other chars */ - buf= my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15, MYF(MY_WME)); + buf= (char*) my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15, + MYF(MY_WME)); CHARSET_INFO *cs; + if (!buf) + return; if (!(cs= get_charset(charset_number, MYF(0)))) { strmov(buf+val_offset, "???"); @@ -4072,11 +4111,11 @@ void User_var_log_event::pack_info(Protocol* protocol) } buf[0]= '@'; buf[1]= '`'; + memcpy(buf+2, name, name_len); buf[2+name_len]= '`'; buf[3+name_len]= '='; - memcpy(buf+2, name, name_len); protocol->store(buf, event_len, &my_charset_bin); - my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); + my_free(buf, MYF(0)); } #endif /* !MYSQL_CLIENT */ @@ -4116,7 +4155,7 @@ bool User_var_log_event::write(IO_CACHE* file) char buf[UV_NAME_LEN_SIZE]; char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE]; - char buf2[max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2; + uchar buf2[max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2; uint buf1_length; ulong event_length; @@ -4125,7 +4164,7 @@ bool User_var_log_event::write(IO_CACHE* file) if ((buf1[0]= is_null)) { buf1_length= 1; - val_len= 0; + val_len= 0; // Length of 'pos' } else { @@ -4150,7 +4189,7 @@ bool User_var_log_event::write(IO_CACHE* file) break; } case STRING_RESULT: - pos= val; + pos= (uchar*) val; break; case ROW_RESULT: default: @@ -4165,10 +4204,10 @@ bool User_var_log_event::write(IO_CACHE* file) event_length= sizeof(buf)+ name_len + buf1_length + val_len; return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) buf, sizeof(buf)) || - my_b_safe_write(file, (byte*) name, name_len) || - my_b_safe_write(file, (byte*) buf1, buf1_length) || - my_b_safe_write(file, (byte*) pos, val_len)); + my_b_safe_write(file, (uchar*) buf, sizeof(buf)) || + my_b_safe_write(file, (uchar*) name, name_len) || + my_b_safe_write(file, (uchar*) buf1, buf1_length) || + my_b_safe_write(file, pos, val_len)); } #endif @@ -4190,7 +4229,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) } my_b_printf(&cache, "SET @`"); - my_b_write(&cache, (byte*) name, (uint) (name_len)); + my_b_write(&cache, (uchar*) name, (uint) (name_len)); my_b_printf(&cache, "`"); if (is_null) @@ -4221,7 +4260,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) dec.len= 10; dec.buf= dec_buf; - bin2decimal(val+2, &dec, precision, scale); + bin2decimal((uchar*) val+2, &dec, precision, scale); decimal2string(&dec, str_buf, &str_len, 0, 0, 0); str_buf[str_len]= 0; my_b_printf(&cache, ":=%s%s\n", str_buf, print_event_info->delimiter); @@ -4322,7 +4361,7 @@ int User_var_log_event::do_apply_event(RELAY_LOG_INFO const *rli) break; case DECIMAL_RESULT: { - Item_decimal *dec= new Item_decimal(val+2, val[0], val[1]); + Item_decimal *dec= new Item_decimal((uchar*) val+2, val[0], val[1]); it= dec; val= (char *)dec->val_decimal(NULL); val_len= sizeof(my_decimal); @@ -4487,7 +4526,7 @@ bool Slave_log_event::write(IO_CACHE* file) // log and host are already there return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) mem_pool, event_length)); + my_b_safe_write(file, (uchar*) mem_pool, event_length)); } #endif @@ -4630,8 +4669,8 @@ bool Create_file_log_event::write_data_body(IO_CACHE* file) bool res; if ((res= Load_log_event::write_data_body(file)) || fake_base) return res; - return (my_b_safe_write(file, (byte*) "", 1) || - my_b_safe_write(file, (byte*) block, block_len)); + return (my_b_safe_write(file, (uchar*) "", 1) || + my_b_safe_write(file, (uchar*) block, block_len)); } @@ -4642,7 +4681,7 @@ bool Create_file_log_event::write_data_body(IO_CACHE* file) bool Create_file_log_event::write_data_header(IO_CACHE* file) { bool res; - byte buf[CREATE_FILE_HEADER_LEN]; + uchar buf[CREATE_FILE_HEADER_LEN]; if ((res= Load_log_event::write_data_header(file)) || fake_base) return res; int4store(buf + CF_FILE_ID_OFFSET, file_id); @@ -4678,7 +4717,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, uint header_len= description_event->common_header_len; uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1]; uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1]; - if (!(event_buf= my_memdup((byte*) buf, len, MYF(MY_WME))) || + if (!(event_buf= (char*) my_memdup(buf, len, MYF(MY_WME))) || copy_log_event(event_buf,len, ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? load_header_len + header_len : @@ -4804,8 +4843,9 @@ int Create_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli) init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, "Error in Create_file event: " - "could not open file '%s'", fname_buf); + rli->report(ERROR_LEVEL, my_errno, + "Error in Create_file event: could not open file '%s'", + fname_buf); goto err; } @@ -4815,9 +4855,9 @@ int Create_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli) if (write_base(&file)) { strmov(ext, ".info"); // to have it right in the error message - slave_print_msg(ERROR_LEVEL, rli, my_errno, - "Error in Create_file event: could not write to file '%s'", - fname_buf); + rli->report(ERROR_LEVEL, my_errno, + "Error in Create_file event: could not write to file '%s'", + fname_buf); goto err; } end_io_cache(&file); @@ -4829,14 +4869,16 @@ int Create_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli) O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, "Error in Create_file event: " - "could not open file '%s'", fname_buf); + rli->report(ERROR_LEVEL, my_errno, + "Error in Create_file event: could not open file '%s'", + fname_buf); goto err; } - if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP))) + if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, "Error in Create_file event: " - "write to '%s' failed", fname_buf); + rli->report(ERROR_LEVEL, my_errno, + "Error in Create_file event: write to '%s' failed", + fname_buf); goto err; } error=0; // Everything is ok @@ -4901,11 +4943,11 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, #ifndef MYSQL_CLIENT bool Append_block_log_event::write(IO_CACHE* file) { - byte buf[APPEND_BLOCK_HEADER_LEN]; + uchar buf[APPEND_BLOCK_HEADER_LEN]; int4store(buf + AB_FILE_ID_OFFSET, file_id); return (write_header(file, APPEND_BLOCK_HEADER_LEN + block_len) || my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || - my_b_safe_write(file, (byte*) block, block_len)); + my_b_safe_write(file, (uchar*) block, block_len)); } #endif @@ -4975,25 +5017,25 @@ int Append_block_log_event::do_apply_event(RELAY_LOG_INFO const *rli) O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, - "Error in %s event: could not create file '%s'", - get_type_str(), fname); + rli->report(ERROR_LEVEL, my_errno, + "Error in %s event: could not create file '%s'", + get_type_str(), fname); goto err; } } else if ((fd = my_open(fname, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW, MYF(MY_WME))) < 0) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, - "Error in %s event: could not open file '%s'", - get_type_str(), fname); + rli->report(ERROR_LEVEL, my_errno, + "Error in %s event: could not open file '%s'", + get_type_str(), fname); goto err; } - if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP))) + if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, - "Error in %s event: write to '%s' failed", - get_type_str(), fname); + rli->report(ERROR_LEVEL, my_errno, + "Error in %s event: write to '%s' failed", + get_type_str(), fname); goto err; } error=0; @@ -5046,7 +5088,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len, #ifndef MYSQL_CLIENT bool Delete_file_log_event::write(IO_CACHE* file) { - byte buf[DELETE_FILE_HEADER_LEN]; + uchar buf[DELETE_FILE_HEADER_LEN]; int4store(buf + DF_FILE_ID_OFFSET, file_id); return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); @@ -5142,7 +5184,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len, #ifndef MYSQL_CLIENT bool Execute_load_log_event::write(IO_CACHE* file) { - byte buf[EXEC_LOAD_HEADER_LEN]; + uchar buf[EXEC_LOAD_HEADER_LEN]; int4store(buf + EL_FILE_ID_OFFSET, file_id); return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); @@ -5201,8 +5243,9 @@ int Execute_load_log_event::do_apply_event(RELAY_LOG_INFO const *rli) init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, "Error in Exec_load event: " - "could not open file '%s'", fname); + rli->report(ERROR_LEVEL, my_errno, + "Error in Exec_load event: could not open file '%s'", + fname); goto err; } if (!(lev = (Load_log_event*)Log_event::read_log_event(&file, @@ -5210,7 +5253,7 @@ int Execute_load_log_event::do_apply_event(RELAY_LOG_INFO const *rli) rli->relay_log.description_event_for_exec)) || lev->get_type_code() != NEW_LOAD_EVENT) { - slave_print_msg(ERROR_LEVEL, rli, 0, "Error in Exec_load event: " + rli->report(ERROR_LEVEL, 0, "Error in Exec_load event: " "file '%s' appears corrupted", fname); goto err; } @@ -5235,13 +5278,11 @@ int Execute_load_log_event::do_apply_event(RELAY_LOG_INFO const *rli) don't want to overwrite it with the filename. What we want instead is add the filename to the current error message. */ - char *tmp= my_strdup(rli->last_slave_error,MYF(MY_WME)); + char *tmp= my_strdup(rli->last_error().message, MYF(MY_WME)); if (tmp) { - slave_print_msg(ERROR_LEVEL, rli, - rli->last_slave_errno, /* ok to re-use error code */ - "%s. Failed executing load from '%s'", - tmp, fname); + rli->report(ERROR_LEVEL, rli->last_error().number, + "%s. Failed executing load from '%s'", tmp, fname); my_free(tmp,MYF(0)); } goto err; @@ -5360,12 +5401,12 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived() bool Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) { - char buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN]; + uchar buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN]; int4store(buf, file_id); int4store(buf + 4, fn_pos_start); int4store(buf + 4 + 4, fn_pos_end); - *(buf + 4 + 4 + 4)= (char)dup_handling; - return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); + *(buf + 4 + 4 + 4)= (uchar) dup_handling; + return my_b_safe_write(file, buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); } #endif @@ -5388,19 +5429,19 @@ void Execute_load_query_log_event::print(FILE* file, if (local_fname) { - my_b_write(&cache, (byte*) query, fn_pos_start); + my_b_write(&cache, (uchar*) query, fn_pos_start); my_b_printf(&cache, " LOCAL INFILE \'"); my_b_printf(&cache, local_fname); my_b_printf(&cache, "\'"); if (dup_handling == LOAD_DUP_REPLACE) my_b_printf(&cache, " REPLACE"); my_b_printf(&cache, " INTO"); - my_b_write(&cache, (byte*) query + fn_pos_end, q_len-fn_pos_end); + my_b_write(&cache, (uchar*) query + fn_pos_end, q_len-fn_pos_end); my_b_printf(&cache, "%s\n", print_event_info->delimiter); } else { - my_b_write(&cache, (byte*) query, q_len); + my_b_write(&cache, (uchar*) query, q_len); my_b_printf(&cache, "%s\n", print_event_info->delimiter); } @@ -5414,7 +5455,7 @@ void Execute_load_query_log_event::print(FILE* file, void Execute_load_query_log_event::pack_info(Protocol *protocol) { char *buf, *pos; - if (!(buf= my_malloc(9 + db_len + q_len + 10 + 21, MYF(MY_WME)))) + if (!(buf= (char*) my_malloc(9 + db_len + q_len + 10 + 21, MYF(MY_WME)))) return; pos= buf; if (db && db_len) @@ -5444,11 +5485,16 @@ Execute_load_query_log_event::do_apply_event(RELAY_LOG_INFO const *rli) char *fname_end; int error; + buf= (char*) my_malloc(q_len + 1 - (fn_pos_end - fn_pos_start) + + (FN_REFLEN + 10) + 10 + 8 + 5, MYF(MY_WME)); + + DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf, MYF(0)); buf= NULL;); + /* Replace filename and LOCAL keyword in query before executing it */ - if (!(buf = my_malloc(q_len + 1 - (fn_pos_end - fn_pos_start) + - (FN_REFLEN + 10) + 10 + 8 + 5, MYF(MY_WME)))) + if (buf == NULL) { - slave_print_msg(ERROR_LEVEL, rli, my_errno, "Not enough memory"); + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), "Not enough memory"); return 1; } @@ -5508,7 +5554,7 @@ bool sql_ex_info::write_data(IO_CACHE* file) write_str(file, line_term, (uint) line_term_len) || write_str(file, line_start, (uint) line_start_len) || write_str(file, escaped, (uint) escaped_len) || - my_b_safe_write(file,(byte*) &opt_flags,1)); + my_b_safe_write(file,(uchar*) &opt_flags,1)); } else { @@ -5520,7 +5566,7 @@ bool sql_ex_info::write_data(IO_CACHE* file) old_ex.escaped= *escaped; old_ex.opt_flags= opt_flags; old_ex.empty_flags=empty_flags; - return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex)) != 0; + return my_b_safe_write(file, (uchar*) &old_ex, sizeof(old_ex)) != 0; } } @@ -5655,9 +5701,9 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, m_flags= uint2korr(post_start); - byte const *const var_start= - (const byte *)buf + common_header_len + post_header_len; - byte const *const ptr_width= var_start; + uchar const *const var_start= + (const uchar *)buf + common_header_len + post_header_len; + uchar const *const ptr_width= var_start; uchar *ptr_after_width= (uchar*) ptr_width; DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); m_width = net_field_length(&ptr_after_width); @@ -5671,7 +5717,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols", (char*) m_cols.bitmap, no_bytes_in_map(&m_cols)); + DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else { @@ -5695,7 +5741,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols_ai", (char*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); + DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, + no_bytes_in_map(&m_cols_ai)); } else { @@ -5705,13 +5752,13 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, } } - const byte* const ptr_rows_data= (const byte*) ptr_after_width; + const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; - my_size_t const data_size= event_len - (ptr_rows_data - (const byte *) buf); + size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu", - m_table_id, m_flags, m_width, data_size)); + m_table_id, m_flags, m_width, (ulong) data_size)); - m_rows_buf= (byte*)my_malloc(data_size, MYF(MY_WME)); + m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME)); if (likely((bool)m_rows_buf)) { m_rows_end= m_rows_buf + data_size; @@ -5729,15 +5776,15 @@ Rows_log_event::~Rows_log_event() if (m_cols.bitmap == m_bitbuf) // no my_malloc happened m_cols.bitmap= 0; // so no my_free in bitmap_free bitmap_free(&m_cols); // To pair with bitmap_init(). - my_free((gptr)m_rows_buf, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*)m_rows_buf, MYF(MY_ALLOW_ZERO_PTR)); } int Rows_log_event::get_data_size() { int const type_code= get_type_code(); - char buf[sizeof(m_width)+1]; - char *end= net_store_length(buf, (m_width + 7) / 8); + uchar buf[sizeof(m_width)+1]; + uchar *end= net_store_length(buf, (m_width + 7) / 8); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", return 6 + no_bytes_in_map(&m_cols) + (end - buf) + @@ -5756,7 +5803,7 @@ int Rows_log_event::get_data_size() #ifndef MYSQL_CLIENT -int Rows_log_event::do_add_row_data(byte *row_data, my_size_t length) +int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) { /* When the table has a primary key, we would probably want, by default, to @@ -5771,7 +5818,7 @@ int Rows_log_event::do_add_row_data(byte *row_data, my_size_t length) trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("row_data", (const char*)row_data, min(length, 32)); + DBUG_DUMP("row_data", row_data, min(length, 32)); #endif DBUG_ASSERT(m_rows_buf <= m_rows_cur); @@ -5779,14 +5826,14 @@ int Rows_log_event::do_add_row_data(byte *row_data, my_size_t length) DBUG_ASSERT(m_rows_cur <= m_rows_end); /* The cast will always work since m_rows_cur <= m_rows_end */ - if (static_cast<my_size_t>(m_rows_end - m_rows_cur) <= length) + if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) { - my_size_t const block_size= 1024; + size_t const block_size= 1024; my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf; my_ptrdiff_t const new_alloc= block_size * ((cur_size + length + block_size - 1) / block_size); - byte* const new_buf= (byte*)my_realloc((gptr)m_rows_buf, (uint) new_alloc, + uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc, MYF(MY_ALLOW_ZERO_PTR|MY_WME)); if (unlikely(!new_buf)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -5818,7 +5865,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) { DBUG_ENTER("Rows_log_event::do_apply_event(st_relay_log_info*)"); int error= 0; - char const *row_start= (char const *)m_rows_buf; + uchar const *row_start= m_rows_buf; /* If m_table_id == ~0UL, then we have a dummy event that does not @@ -5877,18 +5924,18 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) simplifications (we don't honour --slave-skip-errors) */ uint actual_error= thd->net.last_errno; - slave_print_msg(ERROR_LEVEL, rli, actual_error, - "Error '%s' in %s event: when locking tables", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - get_type_str()); + rli->report(ERROR_LEVEL, actual_error, + "Error '%s' in %s event: when locking tables", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + get_type_str()); thd->is_fatal_error= 1; } else { - slave_print_msg(ERROR_LEVEL, rli, error, - "Error in %s event: when locking tables", - get_type_str()); + rli->report(ERROR_LEVEL, error, + "Error in %s event: when locking tables", + get_type_str()); } const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); DBUG_RETURN(error); @@ -5921,10 +5968,10 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) simplifications (we don't honour --slave-skip-errors) */ uint actual_error= thd->net.last_errno; - slave_print_msg(ERROR_LEVEL, rli, actual_error, - "Error '%s' on reopening tables", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error")); + rli->report(ERROR_LEVEL, actual_error, + "Error '%s' on reopening tables", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error")); thd->query_error= 1; } const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); @@ -6029,15 +6076,15 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) const_cast<RELAY_LOG_INFO*>(rli)->set_flag(RELAY_LOG_INFO::IN_STMT); error= do_before_row_operations(table); - while (error == 0 && row_start < (const char*) m_rows_end) + while (error == 0 && row_start < m_rows_end) { - char const *row_end= NULL; + uchar const *row_end= NULL; if ((error= do_prepare_row(thd, rli, table, row_start, &row_end))) break; // We should perform the after-row operation even in // the case of error DBUG_ASSERT(row_end != NULL); // cannot happen - DBUG_ASSERT(row_end <= (const char*)m_rows_end); + DBUG_ASSERT(row_end <= m_rows_end); /* in_use can have been set to NULL in close_tables_for_reopen */ THD* old_thd= table->in_use; @@ -6056,9 +6103,9 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) break; default: - slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno, - "Error in %s event: row application failed", - get_type_str()); + rli->report(ERROR_LEVEL, thd->net.last_errno, + "Error in %s event: row application failed", + get_type_str()); thd->query_error= 1; break; } @@ -6077,13 +6124,13 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) if (error) { /* error has occured during the transaction */ - slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno, - "Error in %s event: error during transaction execution " - "on table %s.%s", - get_type_str(), table->s->db.str, - table->s->table_name.str); + rli->report(ERROR_LEVEL, thd->net.last_errno, + "Error in %s event: error during transaction execution " + "on table %s.%s", + get_type_str(), table->s->db.str, + table->s->table_name.str); - /* + /* If one day we honour --skip-slave-errors in row-based replication, and the error should be skipped, then we would clear mappings, rollback, close tables, but the slave SQL thread would not stop and then may @@ -6130,6 +6177,20 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) DBUG_RETURN(0); } +Log_event::enum_skip_reason +Rows_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +{ + /* + If the slave skip counter is 1 and this event does not end a + statement, then we should not start executing on the next event. + Otherwise, we defer the decision to the normal skipping logic. + */ + if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F)) + return Log_event::EVENT_SKIP_IGNORE; + else + return Log_event::do_shall_skip(rli); +} + int Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) { @@ -6201,9 +6262,11 @@ Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) thd->clear_error(); } else - slave_print_msg(ERROR_LEVEL, rli, error, - "Error in %s event: commit of row events failed", - get_type_str()); + rli->report(ERROR_LEVEL, error, + "Error in %s event: commit of row events failed, " + "table `%s`.`%s`", + get_type_str(), m_table->s->db.str, + m_table->s->table_name.str); } else { @@ -6218,7 +6281,7 @@ Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) #ifndef MYSQL_CLIENT bool Rows_log_event::write_data_header(IO_CACHE *file) { - byte buf[ROWS_HEADER_LEN]; // No need to init the buffer + uchar buf[ROWS_HEADER_LEN]; // No need to init the buffer DBUG_ASSERT(m_table_id != ~0UL); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { @@ -6237,34 +6300,30 @@ bool Rows_log_event::write_data_body(IO_CACHE*file) Note that this should be the number of *bits*, not the number of bytes. */ - char sbuf[sizeof(m_width)]; + uchar sbuf[sizeof(m_width)]; my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; bool res= false; + uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width); + DBUG_ASSERT(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf)); - char *const sbuf_end= net_store_length((char*) sbuf, (uint) m_width); - DBUG_ASSERT(static_cast<my_size_t>(sbuf_end - sbuf) <= sizeof(sbuf)); - - DBUG_DUMP("m_width", sbuf, sbuf_end - sbuf); - res= res || my_b_safe_write(file, - reinterpret_cast<byte*>(sbuf), - sbuf_end - sbuf); + DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); + res= res || my_b_safe_write(file, sbuf, (size_t) (sbuf_end - sbuf)); - DBUG_DUMP("m_cols", (char*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || my_b_safe_write(file, - reinterpret_cast<byte*>(m_cols.bitmap), + DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); + res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); /* TODO[refactor write]: Remove the "down cast" here (and elsewhere). */ if (get_type_code() == UPDATE_ROWS_EVENT) { - DBUG_DUMP("m_cols_ai", (char*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); - res= res || my_b_safe_write(file, - reinterpret_cast<byte*>(m_cols_ai.bitmap), + DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, + no_bytes_in_map(&m_cols_ai)); + res= res || my_b_safe_write(file, (uchar*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); } - DBUG_DUMP("rows",(const char *) m_rows_buf, data_size); - res= res || my_b_safe_write(file, m_rows_buf, (uint) data_size); + DBUG_DUMP("rows", m_rows_buf, data_size); + res= res || my_b_safe_write(file, m_rows_buf, (size_t) data_size); return res; @@ -6277,7 +6336,7 @@ void Rows_log_event::pack_info(Protocol *protocol) char buf[256]; char const *const flagstr= get_flags(STMT_END_F) ? " flags: STMT_END_F" : ""; - my_size_t bytes= my_snprintf(buf, sizeof(buf), + size_t bytes= my_snprintf(buf, sizeof(buf), "table_id: %lu%s", m_table_id, flagstr); protocol->store(buf, bytes, &my_charset_bin); } @@ -6349,7 +6408,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_data_size+= 1 + m_colcnt; // COLCNT and column types /* If malloc fails, catched in is_valid() */ - if ((m_memory= my_malloc(m_colcnt, MYF(MY_WME)))) + if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME)))) { m_coltype= reinterpret_cast<uchar*>(m_memory); for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) @@ -6384,7 +6443,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("event buffer", buf, event_len); + DBUG_DUMP("event buffer", (uchar*) buf, event_len); #endif /* Read the post-header */ @@ -6412,29 +6471,29 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, const char *const vpart= buf + common_header_len + post_header_len; /* Extract the length of the various parts from the buffer */ - byte const *const ptr_dblen= (byte const*)vpart + 0; + uchar const *const ptr_dblen= (uchar const*)vpart + 0; m_dblen= *(uchar*) ptr_dblen; /* Length of database name + counter + terminating null */ - byte const *const ptr_tbllen= ptr_dblen + m_dblen + 2; + uchar const *const ptr_tbllen= ptr_dblen + m_dblen + 2; m_tbllen= *(uchar*) ptr_tbllen; /* Length of table name + counter + terminating null */ - byte const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2; + uchar const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2; uchar *ptr_after_colcnt= (uchar*) ptr_colcnt; m_colcnt= net_field_length(&ptr_after_colcnt); DBUG_PRINT("info",("m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld", - m_dblen, (long) (ptr_dblen-(const byte*)vpart), - m_tbllen, (long) (ptr_tbllen-(const byte*)vpart), - m_colcnt, (long) (ptr_colcnt-(const byte*)vpart))); + (ulong) m_dblen, (long) (ptr_dblen-(const uchar*)vpart), + (ulong) m_tbllen, (long) (ptr_tbllen-(const uchar*)vpart), + m_colcnt, (long) (ptr_colcnt-(const uchar*)vpart))); /* Allocate mem for all fields in one go. If fails, catched in is_valid() */ - m_memory= my_multi_malloc(MYF(MY_WME), - &m_dbnam, m_dblen + 1, - &m_tblnam, m_tbllen + 1, - &m_coltype, m_colcnt, - NULL); + m_memory= (uchar*) my_multi_malloc(MYF(MY_WME), + &m_dbnam, (uint) m_dblen + 1, + &m_tblnam, (uint) m_tbllen + 1, + &m_coltype, (uint) m_colcnt, + NullS); if (m_memory) { @@ -6467,8 +6526,11 @@ Table_map_log_event::~Table_map_log_event() #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) { + RPL_TABLE_LIST *table_list; + char *db_mem, *tname_mem; + size_t dummy_len; + void *memory; DBUG_ENTER("Table_map_log_event::do_apply_event(st_relay_log_info*)"); - DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ @@ -6476,19 +6538,13 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) thd->query_id= next_query_id(); pthread_mutex_unlock(&LOCK_thread_count); - RPL_TABLE_LIST *table_list; - char *db_mem, *tname_mem; - void *const memory= - my_multi_malloc(MYF(MY_WME), - &table_list, sizeof(RPL_TABLE_LIST), - &db_mem, NAME_LEN + 1, - &tname_mem, NAME_LEN + 1, - NULL); - - if (memory == NULL) + if (!(memory= my_multi_malloc(MYF(MY_WME), + &table_list, (uint) sizeof(RPL_TABLE_LIST), + &db_mem, (uint) NAME_LEN + 1, + &tname_mem, (uint) NAME_LEN + 1, + NullS))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - uint dummy_len; bzero(table_list, sizeof(*table_list)); table_list->db = db_mem; table_list->alias= table_list->table_name = tname_mem; @@ -6504,7 +6560,7 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) if (!rpl_filter->db_ok(table_list->db) || (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))) { - my_free((gptr) memory, MYF(MY_WME)); + my_free(memory, MYF(MY_WME)); } else { @@ -6556,11 +6612,11 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) simplifications (we don't honour --slave-skip-errors) */ uint actual_error= thd->net.last_errno; - slave_print_msg(ERROR_LEVEL, rli, actual_error, - "Error '%s' on opening table `%s`.`%s`", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - table_list->db, table_list->table_name); + rli->report(ERROR_LEVEL, actual_error, + "Error '%s' on opening table `%s`.`%s`", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + table_list->db, table_list->table_name); thd->query_error= 1; } goto err; @@ -6599,10 +6655,23 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) DBUG_RETURN(error); err: - my_free((gptr) memory, MYF(MY_WME)); + my_free(memory, MYF(MY_WME)); DBUG_RETURN(error); } +Log_event::enum_skip_reason +Table_map_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +{ + /* + If the slave skip counter is 1, then we should not start executing + on the next event. + */ + if (rli->slave_skip_counter == 1) + return Log_event::EVENT_SKIP_IGNORE; + else + return Log_event::do_shall_skip(rli); +} + int Table_map_log_event::do_update_pos(RELAY_LOG_INFO *rli) { rli->inc_event_relay_log_pos(); @@ -6615,7 +6684,7 @@ int Table_map_log_event::do_update_pos(RELAY_LOG_INFO *rli) bool Table_map_log_event::write_data_header(IO_CACHE *file) { DBUG_ASSERT(m_table_id != ~0UL); - byte buf[TABLE_MAP_HEADER_LEN]; + uchar buf[TABLE_MAP_HEADER_LEN]; DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { int4store(buf + 0, m_table_id); @@ -6635,20 +6704,19 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) DBUG_ASSERT(m_dblen < 128); DBUG_ASSERT(m_tbllen < 128); - byte const dbuf[]= { (byte) m_dblen }; - byte const tbuf[]= { (byte) m_tbllen }; + uchar const dbuf[]= { (uchar) m_dblen }; + uchar const tbuf[]= { (uchar) m_tbllen }; - char cbuf[sizeof(m_colcnt)]; - char *const cbuf_end= net_store_length((char*) cbuf, (uint) m_colcnt); - DBUG_ASSERT(static_cast<my_size_t>(cbuf_end - cbuf) <= sizeof(cbuf)); + uchar cbuf[sizeof(m_colcnt)]; + uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt); + DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf)); return (my_b_safe_write(file, dbuf, sizeof(dbuf)) || - my_b_safe_write(file, (const byte*)m_dbnam, m_dblen+1) || + my_b_safe_write(file, (const uchar*)m_dbnam, m_dblen+1) || my_b_safe_write(file, tbuf, sizeof(tbuf)) || - my_b_safe_write(file, (const byte*)m_tblnam, m_tbllen+1) || - my_b_safe_write(file, reinterpret_cast<byte*>(cbuf), - cbuf_end - (char*) cbuf) || - my_b_safe_write(file, reinterpret_cast<byte*>(m_coltype), m_colcnt)); + my_b_safe_write(file, (const uchar*)m_tblnam, m_tbllen+1) || + my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) || + my_b_safe_write(file, m_coltype, m_colcnt)); } #endif @@ -6663,7 +6731,7 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) void Table_map_log_event::pack_info(Protocol *protocol) { char buf[256]; - my_size_t bytes= my_snprintf(buf, sizeof(buf), + size_t bytes= my_snprintf(buf, sizeof(buf), "table_id: %lu (%s.%s)", m_table_id, m_dbnam, m_tblnam); protocol->store(buf, bytes, &my_charset_bin); @@ -6737,10 +6805,23 @@ int Write_rows_log_event::do_before_row_operations(TABLE *table) lex->duplicates flag. */ thd->lex->sql_command= SQLCOM_REPLACE; - - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); // Needed for ndbcluster - table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); // Needed for ndbcluster - table->file->extra(HA_EXTRA_IGNORE_NO_KEY); // Needed for ndbcluster + /* + Do not raise the error flag in case of hitting to an unique attribute + */ + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + /* + NDB specific: update from ndb master wrapped as Write_rows + */ + /* + so that the event should be applied to replace slave's row + */ + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + /* + NDB specific: if update from ndb master wrapped as Write_rows + does not find the row it's assumed idempotent binlog applying + is taking place; don't raise the error. + */ + table->file->extra(HA_EXTRA_IGNORE_NO_KEY); /* TODO: the cluster team (Tomas?) says that it's better if the engine knows how many rows are going to be inserted, then it can allocate needed memory @@ -6768,24 +6849,38 @@ int Write_rows_log_event::do_before_row_operations(TABLE *table) int Write_rows_log_event::do_after_row_operations(TABLE *table, int error) { - if (error == 0) - error= table->file->ha_end_bulk_insert(); - return error; + int local_error= 0; + table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); + /* + reseting the extra with + table->file->extra(HA_EXTRA_NO_IGNORE_NO_KEY); + fires bug#27077 + todo: explain or fix + */ + if ((local_error= table->file->ha_end_bulk_insert())) + { + table->file->print_error(local_error, MYF(0)); + } + return error? error : local_error; } int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *const row_start, - char const **const row_end) + uchar const *const row_start, + uchar const **const row_end) { DBUG_ASSERT(table != NULL); DBUG_ASSERT(row_start && row_end); - int error; - error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, - &m_master_reclength, table->write_set, WRITE_ROWS_EVENT); + if (int error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->write_set, WRITE_ROWS_EVENT)) + { + thd->net.last_errno= error; + return error; + } bitmap_copy(table->read_set, table->write_set); - return error; + return 0; } /* @@ -6841,7 +6936,7 @@ namespace { */ static int copy_extra_record_fields(TABLE *table, - my_size_t master_reclength, + size_t master_reclength, my_ptrdiff_t master_fields) { DBUG_PRINT("info", ("Copying to 0x%lx " @@ -6983,7 +7078,7 @@ replace_record(THD *thd, TABLE *table, auto_afree_ptr<char> key(NULL); #ifndef DBUG_OFF - DBUG_DUMP("record[0]",(const char *) table->record[0], table->s->reclength); + DBUG_DUMP("record[0]", table->record[0], table->s->reclength); DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set); DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set); #endif @@ -7034,9 +7129,9 @@ replace_record(THD *thd, TABLE *table, DBUG_RETURN(ENOMEM); } - key_copy((byte*)key.get(), table->record[0], table->key_info + keynum, 0); + key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum, 0); error= table->file->index_read_idx(table->record[1], keynum, - (const byte*)key.get(), + (const uchar*)key.get(), HA_WHOLE_KEY, HA_READ_KEY_EXACT); if (error) @@ -7134,7 +7229,7 @@ static bool record_compare(TABLE *table) */ bool result= FALSE; - byte saved_x[2], saved_filler[2]; + uchar saved_x[2], saved_filler[2]; if (table->s->null_bytes > 0) { @@ -7217,15 +7312,15 @@ record_compare_exit: <code>table->record[1]</code>, error code otherwise. */ -static int find_and_fetch_row(TABLE *table, byte *key) +static int find_and_fetch_row(TABLE *table, uchar *key) { - DBUG_ENTER("find_and_fetch_row(TABLE *table, byte *key, byte *record)"); + DBUG_ENTER("find_and_fetch_row(TABLE *table, uchar *key, uchar *record)"); DBUG_PRINT("enter", ("table: 0x%lx, key: 0x%lx record: 0x%lx", (long) table, (long) key, (long) table->record[1])); DBUG_ASSERT(table->in_use != NULL); - DBUG_DUMP("record[0]",(const char *) table->record[0], table->s->reclength); + DBUG_DUMP("record[0]", table->record[0], table->s->reclength); if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION) && table->s->primary_key < MAX_KEY) @@ -7274,8 +7369,8 @@ static int find_and_fetch_row(TABLE *table, byte *key) trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("table->record[0]", (const char *)table->record[0], table->s->reclength); - DBUG_DUMP("table->record[1]", (const char *)table->record[1], table->s->reclength); + DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength); #endif /* @@ -7300,8 +7395,8 @@ static int find_and_fetch_row(TABLE *table, byte *key) trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("table->record[0]", (const char *)table->record[0], table->s->reclength); - DBUG_DUMP("table->record[1]", (const char *)table->record[1], table->s->reclength); + DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength); #endif /* Below is a minor "optimization". If the key (i.e., key number @@ -7369,11 +7464,10 @@ static int find_and_fetch_row(TABLE *table, byte *key) { error= table->file->rnd_next(table->record[1]); - DBUG_DUMP("record[0]",(const char *) table->record[0], table->s->reclength); - DBUG_DUMP("record[1]",(const char *) table->record[1], table->s->reclength); + DBUG_DUMP("record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("record[1]", table->record[1], table->s->reclength); - switch (error) - { + switch (error) { case 0: case HA_ERR_RECORD_DELETED: break; @@ -7458,16 +7552,17 @@ int Delete_rows_log_event::do_before_row_operations(TABLE *table) if (table->s->keys > 0) { - m_memory= - my_multi_malloc(MYF(MY_WME), - &m_after_image, table->s->reclength, - &m_key, table->key_info->key_length, - NULL); + m_memory= (uchar*) my_multi_malloc(MYF(MY_WME), + &m_after_image, + (uint) table->s->reclength, + &m_key, + (uint) table->key_info->key_length, + NullS); } else { - m_after_image= (byte*)my_malloc(table->s->reclength, MYF(MY_WME)); - m_memory= (gptr)m_after_image; + m_after_image= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)); + m_memory= (uchar*)m_after_image; m_key= NULL; } if (!m_memory) @@ -7490,10 +7585,9 @@ int Delete_rows_log_event::do_after_row_operations(TABLE *table, int error) int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *const row_start, - char const **const row_end) + uchar const *const row_start, + uchar const **const row_end) { - int error; DBUG_ASSERT(row_start && row_end); /* This assertion actually checks that there is at least as many @@ -7501,8 +7595,13 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, */ DBUG_ASSERT(table->s->fields >= m_width); - error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, - &m_master_reclength, table->read_set, DELETE_ROWS_EVENT); + if (int error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->read_set, DELETE_ROWS_EVENT)) + { + thd->net.last_errno= error; + return error; + } + /* If we will access rows using the random access method, m_key will be set to NULL, so we do not need to make a key copy in that case. @@ -7514,7 +7613,7 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, key_copy(m_key, table->record[0], key_info, 0); } - return error; + return 0; } int Delete_rows_log_event::do_exec_row(TABLE *table) @@ -7630,16 +7729,17 @@ int Update_rows_log_event::do_before_row_operations(TABLE *table) if (table->s->keys > 0) { - m_memory= - my_multi_malloc(MYF(MY_WME), - &m_after_image, table->s->reclength, - &m_key, table->key_info->key_length, - NULL); + m_memory= (uchar*) my_multi_malloc(MYF(MY_WME), + &m_after_image, + (uint) table->s->reclength, + &m_key, + (uint) table->key_info->key_length, + NullS); } else { - m_after_image= (byte*)my_malloc(table->s->reclength, MYF(MY_WME)); - m_memory= (gptr)m_after_image; + m_after_image= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME)); + m_memory= m_after_image; m_key= NULL; } if (!m_memory) @@ -7664,8 +7764,8 @@ int Update_rows_log_event::do_after_row_operations(TABLE *table, int error) int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *const row_start, - char const **const row_end) + uchar const *const row_start, + uchar const **const row_end) { int error; DBUG_ASSERT(row_start && row_end); @@ -7682,13 +7782,23 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, */ /* record[0] is the before image for the update */ - error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, - &m_master_reclength, table->read_set, UPDATE_ROWS_EVENT); + if ((error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->read_set, UPDATE_ROWS_EVENT))) + { + thd->net.last_errno= error; + return error; + } + store_record(table, record[1]); - char const *next_start = *row_end; + uchar const *next_start = *row_end; /* m_after_image is the after image for the update */ - error= unpack_row(rli, table, m_width, next_start, &m_cols_ai, row_end, - &m_master_reclength, table->write_set, UPDATE_ROWS_EVENT); + if ((error= unpack_row(rli, table, m_width, next_start, &m_cols_ai, row_end, + &m_master_reclength, table->write_set, UPDATE_ROWS_EVENT))) + { + thd->net.last_errno= error; + return error; + } + bmove_align(m_after_image, table->record[0], table->s->reclength); restore_record(table, record[1]); @@ -7697,8 +7807,8 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("record[0]", (const char *)table->record[0], table->s->reclength); - DBUG_DUMP("m_after_image", (const char *)m_after_image, table->s->reclength); + DBUG_DUMP("record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("m_after_image", m_after_image, table->s->reclength); #endif /* @@ -7802,7 +7912,7 @@ Incident_log_event::description() const DBUG_PRINT("info", ("m_incident: %d", m_incident)); DBUG_ASSERT(0 <= m_incident); - DBUG_ASSERT((my_size_t) m_incident <= sizeof(description)/sizeof(*description)); + DBUG_ASSERT((size_t) m_incident <= sizeof(description)/sizeof(*description)); return description[m_incident]; } @@ -7812,7 +7922,7 @@ Incident_log_event::description() const void Incident_log_event::pack_info(Protocol *protocol) { char buf[256]; - my_size_t bytes; + size_t bytes; if (m_message.length > 0) bytes= my_snprintf(buf, sizeof(buf), "#%d (%s)", m_incident, description()); @@ -7843,10 +7953,10 @@ int Incident_log_event::do_apply_event(RELAY_LOG_INFO const *rli) { DBUG_ENTER("Incident_log_event::do_apply_event"); - slave_print_msg(ERROR_LEVEL, rli, ER_SLAVE_INCIDENT, - ER(ER_SLAVE_INCIDENT), - description(), - m_message.length > 0 ? m_message.str : "<none>"); + rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT, + ER(ER_SLAVE_INCIDENT), + description(), + m_message.length > 0 ? m_message.str : "<none>"); DBUG_RETURN(1); } #endif @@ -7856,7 +7966,7 @@ Incident_log_event::write_data_header(IO_CACHE *file) { DBUG_ENTER("Incident_log_event::write_data_header"); DBUG_PRINT("enter", ("m_incident: %d", m_incident)); - byte buf[sizeof(int16)]; + uchar buf[sizeof(int16)]; int2store(buf, (int16) m_incident); DBUG_RETURN(my_b_safe_write(file, buf, sizeof(buf))); } diff --git a/sql/log_event.h b/sql/log_event.h index 4e43822cb38..6787aa08016 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -753,7 +753,7 @@ public: static void operator delete(void *ptr, size_t size) { - my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); + my_free((uchar*) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); } /* Placement version of the above operators */ @@ -1023,7 +1023,8 @@ public: #ifndef MYSQL_CLIENT Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, - bool using_trans, bool suppress_use); + bool using_trans, bool suppress_use, + THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); @@ -1040,7 +1041,7 @@ public: ~Query_log_event() { if (data_buf) - my_free((gptr) data_buf, MYF(0)); + my_free((uchar*) data_buf, MYF(0)); } Log_event_type get_type_code() { return QUERY_EVENT; } #ifndef MYSQL_CLIENT @@ -1362,7 +1363,7 @@ public: Format_description_log_event(uint8 binlog_ver, const char* server_ver=0); Format_description_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event); - ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); } + ~Format_description_log_event() { my_free((uchar*)post_header_len, MYF(0)); } Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;} #ifndef MYSQL_CLIENT bool write(IO_CACHE* file); @@ -1645,7 +1646,7 @@ public: ~Rotate_log_event() { if (flags & DUP_NAME) - my_free((gptr) new_log_ident, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*) new_log_ident, MYF(MY_ALLOW_ZERO_PTR)); } Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} @@ -2066,23 +2067,24 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); #endif #ifndef MYSQL_CLIENT - TABLE *m_table; + TABLE *m_table; #endif char const *m_dbnam; - my_size_t m_dblen; + size_t m_dblen; char const *m_tblnam; - my_size_t m_tbllen; + size_t m_tbllen; ulong m_colcnt; - unsigned char *m_coltype; + uchar *m_coltype; - gptr m_memory; + uchar *m_memory; ulong m_table_id; flag_set m_flags; - my_size_t m_data_size; + size_t m_data_size; }; @@ -2160,7 +2162,7 @@ public: #endif #ifndef MYSQL_CLIENT - int add_row_data(byte *data, my_size_t length) + int add_row_data(uchar *data, size_t length) { return do_add_row_data(data,length); } @@ -2170,7 +2172,7 @@ public: virtual int get_data_size(); MY_BITMAP const *get_cols() const { return &m_cols; } - my_size_t get_width() const { return m_width; } + size_t get_width() const { return m_width; } ulong get_table_id() const { return m_table_id; } #ifndef MYSQL_CLIENT @@ -2209,7 +2211,7 @@ protected: #endif #ifndef MYSQL_CLIENT - virtual int do_add_row_data(byte *data, my_size_t length); + virtual int do_add_row_data(uchar *data, size_t length); #endif #ifndef MYSQL_CLIENT @@ -2233,9 +2235,9 @@ protected: uint32 m_bitbuf[128/(sizeof(uint32)*8)]; uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)]; - byte *m_rows_buf; /* The rows in packed format */ - byte *m_rows_cur; /* One-after the end of the data */ - byte *m_rows_end; /* One-after the end of the allocated space */ + uchar *m_rows_buf; /* The rows in packed format */ + uchar *m_rows_cur; /* One-after the end of the data */ + uchar *m_rows_end; /* One-after the end of the allocated space */ flag_set m_flags; /* Flags for row-level events */ @@ -2244,6 +2246,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); /* Primitive to prepare for a sequence of row executions. @@ -2293,7 +2296,8 @@ private: Error code, if something went wrong, 0 otherwise. */ virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end) = 0; + uchar const *row_start, + uchar const **row_end) = 0; /* Primitive to do the actual execution necessary for a row. @@ -2341,9 +2345,9 @@ public: bool is_transactional, MY_BITMAP *cols, uint fields, - const byte *before_record + const uchar *before_record __attribute__((unused)), - const byte *after_record) + const uchar *after_record) { return thd->binlog_write_row(table, is_transactional, cols, fields, after_record); @@ -2358,13 +2362,13 @@ private: #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - gptr m_memory; - byte *m_after_image; + uchar *m_memory; + uchar *m_after_image; virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif }; @@ -2416,8 +2420,8 @@ public: bool is_transactional, MY_BITMAP *cols, uint fields, - const byte *before_record, - const byte *after_record) + const uchar *before_record, + const uchar *after_record) { return thd->binlog_update_row(table, is_transactional, cols, fields, before_record, after_record); @@ -2437,14 +2441,14 @@ protected: #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - gptr m_memory; - byte *m_key; - byte *m_after_image; + uchar *m_memory; + uchar *m_key; + uchar *m_after_image; virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ }; @@ -2491,8 +2495,8 @@ public: bool is_transactional, MY_BITMAP *cols, uint fields, - const byte *before_record, - const byte *after_record + const uchar *before_record, + const uchar *after_record __attribute__((unused))) { return thd->binlog_delete_row(table, is_transactional, @@ -2508,14 +2512,14 @@ protected: #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - gptr m_memory; - byte *m_key; - byte *m_after_image; + uchar *m_memory; + uchar *m_key; + uchar *m_after_image; virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif }; diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 5153dff0e55..e6a9dd50c08 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -8,8 +8,8 @@ int Write_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *row_start, - char const **row_end) + uchar const *row_start, + uchar const **row_end) { DBUG_ASSERT(table != NULL); DBUG_ASSERT(row_start && row_end); @@ -28,8 +28,8 @@ int Delete_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *row_start, - char const **row_end) + uchar const *row_start, + uchar const **row_end) { int error; DBUG_ASSERT(row_start && row_end); @@ -61,8 +61,8 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd, int Update_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, TABLE *table, - char const *row_start, - char const **row_end) + uchar const *row_start, + uchar const **row_end) { int error; DBUG_ASSERT(row_start && row_end); @@ -84,9 +84,8 @@ int Update_rows_log_event_old::do_prepare_row(THD *thd, row_start, &m_cols, row_end, &m_master_reclength, table->write_set, PRE_GA_UPDATE_ROWS_EVENT); - DBUG_DUMP("record[0]", (const char*) table->record[0], table->s->reclength); - DBUG_DUMP("m_after_image", (const char *) m_after_image, table->s->reclength); - + DBUG_DUMP("record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("m_after_image", m_after_image, table->s->reclength); /* If we will access rows using the random access method, m_key will diff --git a/sql/log_event_old.h b/sql/log_event_old.h index 87b11aea3a3..7c2932360f5 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -50,7 +50,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); #endif }; @@ -84,7 +84,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ }; @@ -118,7 +118,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, - char const *row_start, char const **row_end); + uchar const *row_start, uchar const **row_end); #endif }; diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index f237f15dbc9..5d9d6d834b4 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -40,8 +40,8 @@ extern "C" { ** Returns 0 if record read */ -int _my_b_net_read(register IO_CACHE *info, byte *Buffer, - uint Count __attribute__((unused))) +int _my_b_net_read(register IO_CACHE *info, uchar *Buffer, + size_t Count __attribute__((unused))) { ulong read_length; NET *net= &(current_thd)->net; @@ -61,7 +61,7 @@ int _my_b_net_read(register IO_CACHE *info, byte *Buffer, DBUG_RETURN(1); } /* to set up stuff for my_b_get (no _) */ - info->read_end = (info->read_pos = (byte*) net->read_pos) + read_length; + info->read_end = (info->read_pos = (uchar*) net->read_pos) + read_length; Buffer[0] = info->read_pos[0]; /* length is always 1 */ /* diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 8823fac3393..1f0ebf32795 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -118,7 +118,7 @@ int my_decimal2string(uint mask, const my_decimal *d, E_DEC_OVERFLOW */ -int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec, +int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec, int scale) { int err1= E_DEC_OK, err2; @@ -244,7 +244,7 @@ print_decimal(const my_decimal *dec) /* print decimal with its binary representation */ void -print_decimal_buff(const my_decimal *dec, const byte* ptr, int length) +print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length) { print_decimal(dec); fprintf(DBUG_FILE, "Record: "); diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 17eb75cfdc5..800ae23425b 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -36,13 +36,18 @@ C_MODE_END /* maximum length of buffer in our big digits (uint32) */ #define DECIMAL_BUFF_LENGTH 9 + +/* the number of digits that my_decimal can possibly contain */ +#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9) + + /* maximum guaranteed precision of number in decimal digits (number of our digits * number of decimal digits in one our big digit - number of decimal - digits in one our big digit decreased on 1 (because we always put decimal + digits in one our big digit decreased by 1 (because we always put decimal point on the border of our big digits)) */ -#define DECIMAL_MAX_PRECISION ((DECIMAL_BUFF_LENGTH * 9) - 8*2) +#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) #define DECIMAL_MAX_SCALE 30 #define DECIMAL_NOT_SPECIFIED 31 @@ -50,7 +55,7 @@ C_MODE_END maximum length of string representation (number of maximum decimal digits + 1 position for sign + 1 position for decimal point) */ -#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_PRECISION + 2) +#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) /* maximum size of packet length */ @@ -110,7 +115,7 @@ public: #ifndef DBUG_OFF void print_decimal(const my_decimal *dec); -void print_decimal_buff(const my_decimal *dec, const byte* ptr, int length); +void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length); const char *dbug_decimal_as_string(char *buff, const my_decimal *val); #else #define dbug_decimal_as_string(A) NULL @@ -200,16 +205,15 @@ void my_decimal2decimal(const my_decimal *from, my_decimal *to) } -int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec, +int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec, int scale); inline -int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, +int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec, int scale) { - return check_result(mask, bin2decimal((char *)bin, (decimal_t*) d, prec, - scale)); + return check_result(mask, bin2decimal(bin, (decimal_t*) d, prec, scale)); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b9d5d9f9b34..959345401ea 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -73,38 +73,35 @@ extern const char *primary_key_name; #include "unireg.h" void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size); -gptr sql_alloc(unsigned size); -gptr sql_calloc(unsigned size); +void *sql_alloc(size_t); +void *sql_calloc(size_t); char *sql_strdup(const char *str); -char *sql_strmake(const char *str,uint len); -gptr sql_memdup(const void * ptr,unsigned size); +char *sql_strmake(const char *str, size_t len); +void *sql_memdup(const void * ptr, size_t size); void sql_element_free(void *ptr); -char *sql_strmake_with_convert(const char *str, uint32 arg_length, +char *sql_strmake_with_convert(const char *str, size_t arg_length, CHARSET_INFO *from_cs, - uint32 max_res_length, - CHARSET_INFO *to_cs, uint32 *result_length); + size_t max_res_length, + CHARSET_INFO *to_cs, size_t *result_length); uint kill_one_thread(THD *thd, ulong id, bool only_kill_query); void sql_kill(THD *thd, ulong id, bool only_kill_query); bool net_request_file(NET* net, const char* fname); char* query_table_status(THD *thd,const char *db,const char *table_name); -void net_set_write_timeout(NET *net, uint timeout); -void net_set_read_timeout(NET *net, uint timeout); - -#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); } -#define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } } +#define x_free(A) { my_free((uchar*) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); } +#define safeFree(x) { if(x) { my_free((uchar*) x,MYF(0)); x = NULL; } } #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) #define all_bits_set(A,B) ((A) & (B) != (B)) #define WARN_DEPRECATED(Thd,Ver,Old,New) \ do { \ DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \ - if (((gptr)Thd) != NULL) \ + if (((uchar*)Thd) != NULL) \ push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \ ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \ (Old), (Ver), (New)); \ else \ - sql_print_warning("The syntax %s is deprecated and will be removed " \ + sql_print_warning("The syntax '%s' is deprecated and will be removed " \ "in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \ } while(0) @@ -178,7 +175,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define STACK_MIN_SIZE 12000 // Abort if less stack during eval. #define STACK_MIN_SIZE_FOR_OPEN 1024*80 -#define STACK_BUFF_ALLOC 256 // For stack overrun checks +#define STACK_BUFF_ALLOC 352 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif @@ -385,7 +382,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define MODE_NO_KEY_OPTIONS 8192 #define MODE_NO_TABLE_OPTIONS 16384 #define MODE_NO_FIELD_OPTIONS 32768 -#define MODE_MYSQL323 65536 +#define MODE_MYSQL323 65536L #define MODE_MYSQL40 (MODE_MYSQL323*2) #define MODE_ANSI (MODE_MYSQL40*2) #define MODE_NO_AUTO_VALUE_ON_ZERO (MODE_ANSI*2) @@ -400,6 +397,8 @@ MY_LOCALE *my_locale_by_number(uint number); #define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2) #define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2) #define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2) +#define MODE_PAD_CHAR_TO_FULL_LENGTH (ULL(1) << 31) + /* Replication uses 8 bytes to store SQL_MODE in the binary log. The day you use strictly more than 64 bits by adding one more define above, you should @@ -499,8 +498,8 @@ class THD; typedef struct st_sql_list { uint elements; - byte *first; - byte **next; + uchar *first; + uchar **next; st_sql_list() {} /* Remove gcc warning */ inline void empty() @@ -509,7 +508,7 @@ typedef struct st_sql_list { first=0; next= &first; } - inline void link_in_list(byte *element,byte **next_ptr) + inline void link_in_list(uchar *element,uchar **next_ptr) { elements++; (*next)=element; @@ -619,6 +618,8 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg, uint max_char_length, CHARSET_INFO *cs, bool no_error); +bool parse_sql(THD *thd, class Lex_input_stream *lip); + enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6 @@ -887,9 +888,9 @@ my_bool is_partition_management(LEX *lex); All methods presume that there is at least one field to change. */ -void set_field_ptr(Field **ptr, const byte *new_buf, const byte *old_buf); -void set_key_field_ptr(KEY *key_info, const byte *new_buf, - const byte *old_buf); +void set_field_ptr(Field **ptr, const uchar *new_buf, const uchar *old_buf); +void set_key_field_ptr(KEY *key_info, const uchar *new_buf, + const uchar *old_buf); bool mysql_backup_table(THD* thd, TABLE_LIST* table_list); bool mysql_restore_table(THD* thd, TABLE_LIST* table_list); @@ -909,7 +910,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list, bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list); int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache, KEY_CACHE *dst_cache); -TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list); +TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list); bool mysql_xa_recover(THD *thd); @@ -953,40 +954,33 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, bool table_cant_handle_bit_fields, bool make_copy_field, uint convert_blob_length); -void sp_prepare_create_field(THD *thd, create_field *sql_field); -int prepare_create_field(create_field *sql_field, +void sp_prepare_create_field(THD *thd, Create_field *sql_field); +int prepare_create_field(Create_field *sql_field, uint *blob_columns, int *timestamps, int *timestamps_with_niladic, longlong table_flags); bool mysql_create_table(THD *thd,const char *db, const char *table_name, HA_CREATE_INFO *create_info, - List<create_field> &fields, List<Key> &keys, - bool tmp_table, uint select_field_count, - bool use_copy_create_info); + Alter_info *alter_info, + bool tmp_table, uint select_field_count); bool mysql_create_table_no_lock(THD *thd, const char *db, const char *table_name, HA_CREATE_INFO *create_info, - List<create_field> &fields, List<Key> &keys, - bool tmp_table, uint select_field_count, - bool use_copy_create_info); + Alter_info *alter_info, + bool tmp_table, uint select_field_count); bool mysql_alter_table(THD *thd, char *new_db, char *new_name, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, - List<create_field> &fields, - List<Key> &keys, - uint order_num, ORDER *order, bool ignore, - ALTER_INFO *alter_info, bool do_send_ok); -bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); + Alter_info *alter_info, + uint order_num, ORDER *order, bool ignore); +bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, - HA_CREATE_INFO *create_info, - Table_ident *src_table); + TABLE_LIST *src_table, + HA_CREATE_INFO *create_info); bool mysql_rename_table(handlerton *base, const char *old_db, const char * old_name, const char *new_db, const char * new_name, uint flags); -bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys); -bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, - ALTER_INFO *alter_info); bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order); int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, @@ -1032,8 +1026,11 @@ TABLE *table_cache_insert_placeholder(THD *thd, const char *key, bool lock_table_name_if_not_cached(THD *thd, const char *db, const char *table_name, TABLE **table); TABLE *find_locked_table(THD *thd, const char *db,const char *table_name); +bool reopen_table(TABLE *table); bool reopen_tables(THD *thd,bool get_locks,bool in_refresh); -bool close_data_tables(THD *thd,const char *db, const char *table_name); +void close_data_files_and_morph_locks(THD *thd, const char *db, + const char *table_name); +void close_handle_and_leave_table_as_lock(TABLE *table); bool wait_for_tables(THD *thd); bool table_is_used(TABLE *table, bool wait_for_name_lock); TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name); @@ -1183,7 +1180,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum enum_field_types t char *change, List<String> *interval_list, CHARSET_INFO *cs, uint uint_geom_type); -create_field * new_create_field(THD *thd, char *field_name, enum_field_types type, +Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type, char *length, char *decimals, uint type_modifier, Item *default_value, Item *on_update_value, @@ -1278,6 +1275,7 @@ int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); bool open_and_lock_tables(THD *thd,TABLE_LIST *tables); bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags); int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen); +int decide_logging_format(THD *thd, TABLE_LIST *tables); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(handlerton *base, char *path); @@ -1307,14 +1305,13 @@ char *make_default_log_name(char *buff,const char* log_ext); #ifdef WITH_PARTITION_STORAGE_ENGINE uint fast_alter_partition_table(THD *thd, TABLE *table, - ALTER_INFO *alter_info, + Alter_info *alter_info, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, - List<create_field> *create_list, - List<Key> *key_list, char *db, + char *db, const char *table_name, uint fast_alter_partition); -uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, +uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, handlerton *old_db_type, bool *partition_changed, @@ -1346,20 +1343,16 @@ typedef struct st_lock_param_type ulonglong deleted; THD *thd; HA_CREATE_INFO *create_info; - ALTER_INFO *alter_info; - List<create_field> *create_list; - List<create_field> new_create_list; - List<Key> *key_list; - List<Key> new_key_list; + Alter_info *alter_info; TABLE *table; KEY *key_info_buffer; const char *db; const char *table_name; - const void *pack_frm_data; + uchar *pack_frm_data; enum thr_lock_type old_lock_type; uint key_count; uint db_options; - uint pack_frm_len; + size_t pack_frm_len; partition_info *part_info; } ALTER_PARTITION_PARAM_TYPE; @@ -1522,16 +1515,16 @@ void print_plan(JOIN* join,uint idx, double record_count, double read_time, #endif void mysql_print_status(); /* key.cc */ -int find_ref_key(KEY *key, uint key_count, byte *record, Field *field, +int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, uint *key_length, uint *keypart); -void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length); -void key_restore(byte *to_record, byte *from_key, KEY *key_info, +void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, uint key_length); +void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, uint key_length); -bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length); +bool key_cmp_if_same(TABLE *form,const uchar *key,uint index,uint key_length); void key_unpack(String *to,TABLE *form,uint index); bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields); -int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length); -int key_rec_cmp(void *key_info, byte *a, byte *b); +int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length); +int key_rec_cmp(void *key_info, uchar *a, uchar *b); bool init_errmessage(void); #endif /* MYSQL_SERVER */ @@ -1556,7 +1549,7 @@ bool slow_log_print(THD *thd, const char *query, uint query_length, bool general_log_print(THD *thd, enum enum_server_command command, const char *format,...); -bool fn_format_relative_to_data_home(my_string to, const char *name, +bool fn_format_relative_to_data_home(char * to, const char *name, const char *dir, const char *extension); #ifdef MYSQL_SERVER File open_binlog(IO_CACHE *log, const char *log_file_name, @@ -1598,6 +1591,7 @@ bool check_db_dir_existence(const char *db_name); bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); bool load_db_opt_by_name(THD *thd, const char *db_name, HA_CREATE_INFO *db_create_info); +CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name); bool my_dbopt_init(void); void my_dbopt_cleanup(void); extern int creating_database; // How many database locks are made @@ -1608,6 +1602,7 @@ extern int creating_table; // How many mysql_create_table() are running */ extern time_t server_start_time; +extern uint mysql_data_home_len; extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; @@ -1618,8 +1613,8 @@ extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword; extern const char **errmesg; /* Error messages */ extern const char *myisam_recover_options_str; extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond; -extern const char * const triggers_file_ext; -extern const char * const trigname_file_ext; +extern const char * const TRG_EXT; +extern const char * const TRN_EXT; extern Eq_creator eq_creator; extern Ne_creator ne_creator; extern Gt_creator gt_creator; @@ -1631,8 +1626,6 @@ extern uint reg_ext_length; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN], *opt_tc_log_file; -extern double log_10[32]; -extern double log_01[32]; extern ulonglong log_10_int[20]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; @@ -1676,7 +1669,7 @@ extern ulong log_output_options; extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; extern my_bool opt_character_set_client_handshake; -extern bool volatile abort_loop, shutdown_in_progress, grant_option; +extern bool volatile abort_loop, shutdown_in_progress; extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; @@ -1815,16 +1808,16 @@ void unireg_end(void) __attribute__((noreturn)); bool mysql_create_frm(THD *thd, const char *file_name, const char *db, const char *table, HA_CREATE_INFO *create_info, - List<create_field> &create_field, + List<Create_field> &create_field, uint key_count,KEY *key_info,handler *db_type); int rea_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, - List<create_field> &create_field, + List<Create_field> &create_field, uint key_count,KEY *key_info, handler *file); -int format_number(uint inputflag,uint max_length,my_string pos,uint length, - my_string *errpos); +int format_number(uint inputflag,uint max_length,char * pos,uint length, + char * *errpos); /* table.cc */ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, @@ -1837,10 +1830,10 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg); int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table); -int readfrm(const char *name, const void** data, uint* length); -int writefrm(const char* name, const void* data, uint len); +int readfrm(const char *name, uchar **data, size_t *length); +int writefrm(const char* name, const uchar* data, size_t len); int closefrm(TABLE *table, bool free_share); -int read_string(File file, gptr *to, uint length); +int read_string(File file, uchar* *to, size_t length); void free_blobs(TABLE *table); int set_zone(int nr,int min_zone,int max_zone); ulong convert_period_to_month(ulong period); @@ -1885,7 +1878,7 @@ ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); int test_if_number(char *str,int *res,bool allow_wildcards); -void change_byte(byte *,uint,char,char); +void change_byte(uchar *,uint,char,char); void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors); @@ -1897,7 +1890,7 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, ha_rows max_rows, bool sort_positions, ha_rows *examined_rows); void filesort_free_buffers(TABLE *table, bool full); -void change_double_for_sort(double nr,byte *to); +void change_double_for_sort(double nr,uchar *to); double my_double_round(double value, longlong dec, bool dec_unsigned, bool truncate); int get_quick_record(SQL_SELECT *select); @@ -1905,7 +1898,7 @@ int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); -TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); +TYPELIB *convert_strings_to_array_type(char * *typelibs, char * *end); TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, @@ -1932,6 +1925,12 @@ uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); uint build_table_filename(char *buff, size_t bufflen, const char *db, const char *table, const char *ext, uint flags); + +#define MYSQL50_TABLE_NAME_PREFIX "#mysql50#" +#define MYSQL50_TABLE_NAME_PREFIX_LENGTH 9 + +uint build_table_shadow_filename(char *buff, size_t bufflen, + ALTER_PARTITION_PARAM_TYPE *lpt); /* Flags for conversion functions. */ #define FN_FROM_IS_TMP (1 << 0) #define FN_TO_IS_TMP (1 << 1) @@ -1940,7 +1939,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, /* from hostname.cc */ struct in_addr; -my_string ip_to_hostname(struct in_addr *in,uint *errors); +char * ip_to_hostname(struct in_addr *in,uint *errors); void inc_host_errors(struct in_addr *in); void reset_host_errors(struct in_addr *in); bool hostname_cache_init(); @@ -1965,7 +1964,6 @@ void free_list(I_List <i_string_pair> *list); void free_list(I_List <i_string> *list); /* sql_yacc.cc */ -extern int MYSQLparse(void *thd); #ifndef DBUG_OFF extern void turn_parser_debug_on(); #endif @@ -2104,7 +2102,7 @@ inline bool is_user_table(TABLE * table) #ifndef EMBEDDED_LIBRARY extern "C" void unireg_abort(int exit_code) __attribute__((noreturn)); void kill_delayed_threads(void); -bool check_stack_overrun(THD *thd, long margin, char *dummy); +bool check_stack_overrun(THD *thd, long margin, uchar *dummy); #else #define unireg_abort(exit_code) DBUG_RETURN(exit_code) inline void kill_delayed_threads(void) {} @@ -2157,6 +2155,12 @@ bool schema_table_store_record(THD *thd, TABLE *table); int item_create_init(); void item_create_cleanup(); +inline void lex_string_set(LEX_STRING *lex_str, const char *c_str) +{ + lex_str->str= (char *) c_str; + lex_str->length= strlen(c_str); +} + #endif /* MYSQL_SERVER */ #endif /* MYSQL_CLIENT */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f8a215a130e..0910566fac4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -30,6 +30,10 @@ #include "rpl_injector.h" +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE #if defined(NOT_ENOUGH_TESTED) \ && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000 @@ -216,8 +220,10 @@ static const char *sql_mode_names[]= "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION", + "PAD_CHAR_TO_FULL_LENGTH", NullS }; + static const unsigned int sql_mode_names_len[]= { /*REAL_AS_FLOAT*/ 13, @@ -250,8 +256,10 @@ static const unsigned int sql_mode_names_len[]= /*TRADITIONAL*/ 11, /*NO_AUTO_CREATE_USER*/ 19, /*HIGH_NOT_PRECEDENCE*/ 19, - /*NO_ENGINE_SUBSTITUTION*/ 22 + /*NO_ENGINE_SUBSTITUTION*/ 22, + /*PAD_CHAR_TO_FULL_LENGTH*/ 23 }; + TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", sql_mode_names, (unsigned int *)sql_mode_names_len }; @@ -347,7 +355,15 @@ bool opt_endinfo, using_udf_functions; my_bool locked_in_memory; bool opt_using_transactions, using_update_log; bool volatile abort_loop; -bool volatile shutdown_in_progress, grant_option; +bool volatile shutdown_in_progress; +/** + @brief 'grant_option' is used to indicate if privileges needs + to be checked, in which case the lock, LOCK_grant, is used + to protect access to the grant table. + @note This flag is dropped in 5.1 + @see grant_init() + */ +bool volatile grant_option; my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted my_bool opt_reckless_slave = 0; @@ -462,8 +478,6 @@ ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; const char *log_output_str= "TABLE"; -double log_10[32]; /* 10 potences */ -double log_01[32]; time_t server_start_time; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30]; @@ -479,6 +493,7 @@ key_map key_map_full(0); // Will be initialized later const char *opt_date_time_formats[3]; +uint mysql_data_home_len; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; @@ -1185,7 +1200,7 @@ void clean_up(bool print_message) if (tc_log) tc_log->close(); xid_cache_free(); - delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache); + delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache); multi_keycache_free(); free_status_vars(); end_thr_alarm(1); /* Free allocated memory */ @@ -1232,7 +1247,7 @@ void clean_up(bool print_message) #endif thread_scheduler.end(); finish_client_errs(); - my_free((gptr) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST), + my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST), MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); DBUG_PRINT("quit", ("Error messages freed")); /* Tell main we are ready */ @@ -1410,6 +1425,15 @@ static struct passwd *check_user(const char *user) err: sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); unireg_abort(1); + +#ifdef PR_SET_DUMPABLE + if (test_flags & TEST_CORE_ON_SIGNAL) + { + /* inform kernel that process is dumpable */ + (void) prctl(PR_SET_DUMPABLE, 1); + } +#endif + #endif return NULL; } @@ -1874,9 +1898,11 @@ static void init_signals(void) static void start_signal_handler(void) { +#ifndef EMBEDDED_LIBRARY // Save vm id of this process if (!opt_bootstrap) create_pid_file(); +#endif /* EMBEDDED_LIBRARY */ } @@ -2193,7 +2219,7 @@ the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n", if (!(test_flags & TEST_NO_STACKTRACE)) { fprintf(stderr,"thd: 0x%lx\n",(long) thd); - print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0, + print_stacktrace(thd ? (uchar*) thd->thread_stack : (uchar*) 0, thread_stack); } if (thd) @@ -2220,6 +2246,16 @@ later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\ mysqld that is not statically linked.\n"); #endif +#ifdef HAVE_NPTL + if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL")) + fprintf(stderr,"\n\ +You are running a statically-linked LinuxThreads binary on an NPTL system.\n\ +This can result in crashes on some distributions due to LT/NPTL conflicts.\n\ +You should either build a dynamically-linked binary, or force LinuxThreads\n\ +to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\ +the documentation for your distribution on how to do that.\n"); +#endif + if (locked_in_memory) { fprintf(stderr, "\n\ @@ -2581,7 +2617,7 @@ static void *my_str_malloc_mysqld(size_t size) static void my_str_free_mysqld(void *ptr) { - my_free((gptr)ptr, MYF(MY_FAE)); + my_free((uchar*)ptr, MYF(MY_FAE)); } #endif /* EMBEDDED_LIBRARY */ @@ -3288,7 +3324,7 @@ with --log-bin instead."); } else { - global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC; + global_system_variables.binlog_format= BINLOG_FORMAT_MIXED; } else if (opt_binlog_format_id == BINLOG_FORMAT_UNSPEC) @@ -3759,6 +3795,7 @@ int main(int argc, char **argv) mysql_data_home= mysql_data_home_buff; mysql_data_home[0]=FN_CURLIB; // all paths are relative from here mysql_data_home[1]=0; + mysql_data_home_len= 2; if ((user_info= check_user(mysqld_user))) { @@ -3802,6 +3839,11 @@ we force server id to 2, but this MySQL server will not act as a slave."); freopen(log_error_file,"a+",stderr); FreeConsole(); // Remove window } + else + { + /* Don't show error dialog box when on foreground: it stops the server */ + SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); + } #endif /* @@ -5033,12 +5075,12 @@ enum options_mysqld struct my_option my_long_options[] = { {"help", '?', "Display this help and exit.", - (gptr*) &opt_help, (gptr*) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + (uchar**) &opt_help, (uchar**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT, "Option used by mysql-test for debugging and testing of replication.", - (gptr*) &abort_slave_event_count, (gptr*) &abort_slave_event_count, + (uchar**) &abort_slave_event_count, (uchar**) &abort_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, @@ -5046,33 +5088,33 @@ struct my_option my_long_options[] = "without corresponding xxx_init() or xxx_deinit(). That also means " "that one can load any function from any library, for example exit() " "from libc.so", - (gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs, + (uchar**) &opt_allow_suspicious_udfs, (uchar**) &opt_allow_suspicious_udfs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"auto-increment-increment", OPT_AUTO_INCREMENT, "Auto-increment columns are incremented by this", - (gptr*) &global_system_variables.auto_increment_increment, - (gptr*) &max_system_variables.auto_increment_increment, 0, GET_ULONG, + (uchar**) &global_system_variables.auto_increment_increment, + (uchar**) &max_system_variables.auto_increment_increment, 0, GET_ULONG, OPT_ARG, 1, 1, 65535, 0, 1, 0 }, {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET, "Offset added to Auto-increment columns. Used when auto-increment-increment != 1", - (gptr*) &global_system_variables.auto_increment_offset, - (gptr*) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG, + (uchar**) &global_system_variables.auto_increment_offset, + (uchar**) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG, 1, 1, 65535, 0, 1, 0 }, {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES, "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.", - (gptr*) &sp_automatic_privileges, (gptr*) &sp_automatic_privileges, + (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"basedir", 'b', "Path to installation directory. All paths are usually resolved relative to this.", - (gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, + (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"big-tables", OPT_BIG_TABLES, "Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.", - (gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR, + (uchar**) &my_bind_addr_str, (uchar**) &my_bind_addr_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog_format", OPT_BINLOG_FORMAT, "Does not have any effect without '--log-bin'. " @@ -5086,7 +5128,7 @@ struct my_option my_long_options[] = "If ndbcluster is enabled and binlog_format is `mixed', the format switches" " to 'row' and back implicitly per each query accessing a NDB table." #endif - ,(gptr*) &opt_binlog_format, (gptr*) &opt_binlog_format, + ,(uchar**) &opt_binlog_format, (uchar**) &opt_binlog_format, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-do-db", OPT_BINLOG_DO_DB, "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.", @@ -5098,8 +5140,8 @@ struct my_option my_long_options[] = "The maximum size of a row-based binary log event in bytes. Rows will be " "grouped into events smaller than this size if possible. " "The value has to be a multiple of 256.", - (gptr*) &opt_binlog_rows_event_max_size, - (gptr*) &opt_binlog_rows_event_max_size, 0, + (uchar**) &opt_binlog_rows_event_max_size, + (uchar**) &opt_binlog_rows_event_max_size, 0, GET_ULONG, REQUIRED_ARG, /* def_value */ 1024, /* min_value */ 256, /* max_value */ ULONG_MAX, /* sub_size */ 0, /* block_size */ 256, @@ -5111,61 +5153,61 @@ struct my_option my_long_options[] = #endif {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE, "Don't ignore client side character set value sent during handshake.", - (gptr*) &opt_character_set_client_handshake, - (gptr*) &opt_character_set_client_handshake, + (uchar**) &opt_character_set_client_handshake, + (uchar**) &opt_character_set_client_handshake, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"character-set-filesystem", OPT_CHARACTER_SET_FILESYSTEM, "Set the filesystem character set.", - (gptr*) &character_set_filesystem_name, - (gptr*) &character_set_filesystem_name, + (uchar**) &character_set_filesystem_name, + (uchar**) &character_set_filesystem_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"character-set-server", 'C', "Set the default character set.", - (gptr*) &default_character_set_name, (gptr*) &default_character_set_name, + (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are.", (gptr*) &charsets_dir, - (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", (uchar**) &charsets_dir, + (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"chroot", 'r', "Chroot mysqld daemon during startup.", - (gptr*) &mysqld_chroot, (gptr*) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, + (uchar**) &mysqld_chroot, (uchar**) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.", - (gptr*) &default_collation_name, (gptr*) &default_collation_name, + (uchar**) &default_collation_name, (uchar**) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.", - (gptr*) &global_system_variables.completion_type, - (gptr*) &max_system_variables.completion_type, 0, GET_ULONG, + (uchar**) &global_system_variables.completion_type, + (uchar**) &max_system_variables.completion_type, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", - (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, + (uchar**) &myisam_concurrent_insert, (uchar**) &myisam_concurrent_insert, 0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", - (gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, + (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"datadir", 'h', "Path to the database root.", (gptr*) &mysql_data_home, - (gptr*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"datadir", 'h', "Path to the database root.", (uchar**) &mysql_data_home, + (uchar**) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF - {"debug", '#', "Debug log.", (gptr*) &default_dbug_option, - (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Debug log.", (uchar**) &default_dbug_option, + (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).", - (gptr*) &default_character_set_name, (gptr*) &default_character_set_name, + (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation (deprecated option, use --collation-server instead).", - (gptr*) &default_collation_name, (gptr*) &default_collation_name, + (uchar**) &default_collation_name, (uchar**) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, "Set the default storage engine (table type) for tables.", - (gptr*)&default_storage_engine_str, (gptr*)&default_storage_engine_str, + (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, "(deprecated) Use --default-storage-engine.", - (gptr*)&default_storage_engine_str, (gptr*)&default_storage_engine_str, + (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", - (gptr*) &default_tz_name, (gptr*) &default_tz_name, + (uchar**) &default_tz_name, (uchar**) &default_tz_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.", 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -5175,33 +5217,33 @@ struct my_option my_long_options[] = #ifdef HAVE_OPENSSL {"des-key-file", OPT_DES_KEY_FILE, "Load keys for des_encrypt() and des_encrypt from given file.", - (gptr*) &des_key_file, (gptr*) &des_key_file, 0, GET_STR, REQUIRED_ARG, + (uchar**) &des_key_file, (uchar**) &des_key_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ #ifdef HAVE_REPLICATION {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT, "Option used by mysql-test for debugging and testing of replication.", - (gptr*) &disconnect_slave_event_count, - (gptr*) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, + (uchar**) &disconnect_slave_event_count, + (uchar**) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"enable-locking", OPT_ENABLE_LOCK, "Deprecated option, use --external-locking instead.", - (gptr*) &opt_external_locking, (gptr*) &opt_external_locking, + (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NT__ {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).", - (gptr*) &opt_enable_named_pipe, (gptr*) &opt_enable_named_pipe, 0, GET_BOOL, + (uchar**) &opt_enable_named_pipe, (uchar**) &opt_enable_named_pipe, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.", - (gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, + (uchar**) &opt_do_pstack, (uchar**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"engine-condition-pushdown", OPT_ENGINE_CONDITION_PUSHDOWN, "Push supported query conditions to the storage engine.", - (gptr*) &global_system_variables.engine_condition_pushdown, - (gptr*) &global_system_variables.engine_condition_pushdown, + (uchar**) &global_system_variables.engine_condition_pushdown, + (uchar**) &global_system_variables.engine_condition_pushdown, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, /* See how it's handled in get_one_option() */ {"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.", @@ -5209,7 +5251,7 @@ struct my_option my_long_options[] = {"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.", - (gptr*) &opt_external_locking, (gptr*) &opt_external_locking, + (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5217,55 +5259,55 @@ struct my_option my_long_options[] = easier to do */ {"gdb", OPT_DEBUGGING, "Set up signals usable for debugging", - (gptr*) &opt_debugging, (gptr*) &opt_debugging, + (uchar**) &opt_debugging, (uchar**) &opt_debugging, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"general-log", OPT_GENERAL_LOG, - "Enable|disable general log", (gptr*) &opt_log, - (gptr*) &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Enable|disable general log", (uchar**) &opt_log, + (uchar**) &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_LARGE_PAGES {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \ Disable with --skip-large-pages.", - (gptr*) &opt_large_pages, (gptr*) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, + (uchar**) &opt_large_pages, (uchar**) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection", - (gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC, + (uchar**) &opt_init_connect, (uchar**) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DISABLE_GRANT_OPTIONS {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.", - (gptr*) &opt_init_file, (gptr*) &opt_init_file, 0, GET_STR, REQUIRED_ARG, + (uchar**) &opt_init_file, (uchar**) &opt_init_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master", - (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, + (uchar**) &opt_init_slave, (uchar**) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"language", 'L', + {"language", 'L', "Client error messages in given language. May be given as a full path.", - (gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG, + (uchar**) &language_ptr, (uchar**) &language_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"lc-time-names", OPT_LC_TIME_NAMES, "Set the language used for the month names and the days of the week.", - (gptr*) &lc_time_names_name, - (gptr*) &lc_time_names_name, + (uchar**) &lc_time_names_name, + (uchar**) &lc_time_names_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0).", - (gptr*) &opt_local_infile, - (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, + (uchar**) &opt_local_infile, + (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"log", 'l', "Log connections and queries to file.", (gptr*) &opt_logname, - (gptr*) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"log", 'l', "Log connections and queries to file.", (uchar**) &opt_logname, + (uchar**) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin", OPT_BIN_LOG, "Log update queries in binary format. Optional (but strongly recommended " "to avoid replication problems if server's hostname changes) argument " "should be the chosen location for the binary log files.", - (gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC, + (uchar**) &opt_bin_logname, (uchar**) &opt_bin_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin-index", OPT_BIN_LOG_INDEX, "File that holds the names for last binary log files.", - (gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR, + (uchar**) &opt_binlog_index_name, (uchar**) &opt_binlog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef TO_BE_REMOVED_IN_5_1_OR_6_0 /* @@ -5276,7 +5318,7 @@ Disable with --skip-large-pages.", */ {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, "(deprecated) Use log-bin-trust-function-creators.", - (gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0, + (uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* @@ -5290,13 +5332,13 @@ Disable with --skip-large-pages.", "Note that if ALL connections to this server ALWAYS use row-based binary " "logging, the security issues do not exist and the binary logging cannot " "break, so you can safely set this to 1." - ,(gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0, + ,(uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-error", OPT_ERROR_LOG_FILE, "Error log file.", - (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR, + (uchar**) &log_error_file_ptr, (uchar**) &log_error_file_ptr, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.", - (gptr*) &myisam_log_filename, (gptr*) &myisam_log_filename, 0, GET_STR, + (uchar**) &myisam_log_filename, (uchar**) &myisam_log_filename, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-long-format", '0', "Log some extra information to update log. Please note that this option is deprecated; see --log-short-format option.", @@ -5305,161 +5347,161 @@ Disable with --skip-large-pages.", {"log-output", OPT_LOG_OUTPUT, "Syntax: log-output[=value[,value...]], where \"value\" could be TABLE, " "FILE or NONE.", - (gptr*) &log_output_str, (gptr*) &log_output_str, 0, + (uchar**) &log_output_str, (uchar**) &log_output_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES, "Log queries that are executed without benefit of any index to the slow log if it is open.", - (gptr*) &opt_log_queries_not_using_indexes, (gptr*) &opt_log_queries_not_using_indexes, + (uchar**) &opt_log_queries_not_using_indexes, (uchar**) &opt_log_queries_not_using_indexes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-short-format", OPT_SHORT_LOG_FORMAT, "Don't log extra information to update and slow-query logs.", - (gptr*) &opt_short_log_format, (gptr*) &opt_short_log_format, + (uchar**) &opt_short_log_format, (uchar**) &opt_short_log_format, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slave-updates", OPT_LOG_SLAVE_UPDATES, "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.", - (gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL, + (uchar**) &opt_log_slave_updates, (uchar**) &opt_log_slave_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS, "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.", - (gptr*) &opt_log_slow_admin_statements, - (gptr*) &opt_log_slow_admin_statements, + (uchar**) &opt_log_slow_admin_statements, + (uchar**) &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-queries", OPT_SLOW_QUERY_LOG, "Log slow queries to this log file. Defaults logging to hostname-slow.log file. Must be enabled to activate other slow log options.", - (gptr*) &opt_slow_logname, (gptr*) &opt_slow_logname, 0, GET_STR, OPT_ARG, + (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-tc", OPT_LOG_TC, "Path to transaction coordinator log (used for transactions that affect " "more than one storage engine, when binary log is disabled)", - (gptr*) &opt_tc_log_file, (gptr*) &opt_tc_log_file, 0, GET_STR, + (uchar**) &opt_tc_log_file, (uchar**) &opt_tc_log_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_MMAP {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", - (gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG, + (uchar**) &opt_tc_log_size, (uchar**) &opt_tc_log_size, 0, GET_ULONG, REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0}, #endif {"log-update", OPT_UPDATE_LOG, "The update log is deprecated since version 5.0, is replaced by the binary \ log and this option justs turns on --log-bin instead.", - (gptr*) &opt_update_logname, (gptr*) &opt_update_logname, 0, GET_STR, + (uchar**) &opt_update_logname, (uchar**) &opt_update_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-warnings", 'W', "Log some not critical warnings to the log file.", - (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, + (uchar**) &global_system_variables.log_warnings, + (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES, "INSERT/DELETE/UPDATE has lower priority than selects.", - (gptr*) &global_system_variables.low_priority_updates, - (gptr*) &max_system_variables.low_priority_updates, + (uchar**) &global_system_variables.low_priority_updates, + (uchar**) &max_system_variables.low_priority_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"master-connect-retry", OPT_MASTER_CONNECT_RETRY, "The number of seconds the slave thread will sleep before retrying to connect to the master in case the master goes down or the connection is lost.", - (gptr*) &master_connect_retry, (gptr*) &master_connect_retry, 0, GET_UINT, + (uchar**) &master_connect_retry, (uchar**) &master_connect_retry, 0, GET_UINT, REQUIRED_ARG, 60, 0, 0, 0, 0, 0}, {"master-host", OPT_MASTER_HOST, "Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.", - (gptr*) &master_host, (gptr*) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0, + (uchar**) &master_host, (uchar**) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-info-file", OPT_MASTER_INFO_FILE, "The location and name of the file that remembers the master and where the I/O replication \ thread is in the master's binlogs.", - (gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR, + (uchar**) &master_info_file, (uchar**) &master_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-password", OPT_MASTER_PASSWORD, "The password the slave thread will authenticate with when connecting to the master. If not set, an empty password is assumed.The value in master.info will take precedence if it can be read.", - (gptr*)&master_password, (gptr*)&master_password, 0, + (uchar**)&master_password, (uchar**)&master_password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-port", OPT_MASTER_PORT, "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.", - (gptr*) &master_port, (gptr*) &master_port, 0, GET_UINT, REQUIRED_ARG, + (uchar**) &master_port, (uchar**) &master_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, {"master-retry-count", OPT_MASTER_RETRY_COUNT, "The number of tries the slave will make to connect to the master before giving up.", - (gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG, + (uchar**) &master_retry_count, (uchar**) &master_retry_count, 0, GET_ULONG, REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0}, {"master-ssl", OPT_MASTER_SSL, "Enable the slave to connect to the master using SSL.", - (gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + (uchar**) &master_ssl, (uchar**) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-ca", OPT_MASTER_SSL_CA, "Master SSL CA file. Only applies if you have enabled master-ssl.", - (gptr*) &master_ssl_ca, (gptr*) &master_ssl_ca, 0, GET_STR, OPT_ARG, + (uchar**) &master_ssl_ca, (uchar**) &master_ssl_ca, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-capath", OPT_MASTER_SSL_CAPATH, "Master SSL CA path. Only applies if you have enabled master-ssl.", - (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, + (uchar**) &master_ssl_capath, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cert", OPT_MASTER_SSL_CERT, "Master SSL certificate file name. Only applies if you have enabled \ master-ssl", - (gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG, + (uchar**) &master_ssl_cert, (uchar**) &master_ssl_cert, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER, "Master SSL cipher. Only applies if you have enabled master-ssl.", - (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, + (uchar**) &master_ssl_cipher, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-key", OPT_MASTER_SSL_KEY, "Master SSL keyfile name. Only applies if you have enabled master-ssl.", - (gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG, + (uchar**) &master_ssl_key, (uchar**) &master_ssl_key, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-user", OPT_MASTER_USER, "The username the slave thread will use for authentication when connecting to the master. The user must have FILE privilege. If the master user is not set, user test is assumed. The value in master.info will take precedence if it can be read.", - (gptr*) &master_user, (gptr*) &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0, + (uchar**) &master_user, (uchar**) &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS, "Option used by mysql-test for debugging and testing of replication.", - (gptr*) &max_binlog_dump_events, (gptr*) &max_binlog_dump_events, 0, + (uchar**) &max_binlog_dump_events, (uchar**) &max_binlog_dump_events, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (gptr*) &locked_in_memory, - (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (uchar**) &locked_in_memory, + (uchar**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"myisam-recover", OPT_MYISAM_RECOVER, "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", - (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, + (uchar**) &myisam_recover_options_str, (uchar**) &myisam_recover_options_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE {"ndb-connectstring", OPT_NDB_CONNECTSTRING, "Connect string for ndbcluster.", - (gptr*) &opt_ndb_connectstring, - (gptr*) &opt_ndb_connectstring, + (uchar**) &opt_ndb_connectstring, + (uchar**) &opt_ndb_connectstring, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-mgmd-host", OPT_NDB_MGMD, "Set host and port for ndb_mgmd. Syntax: hostname[:port]", - (gptr*) &opt_ndb_mgmd, - (gptr*) &opt_ndb_mgmd, + (uchar**) &opt_ndb_mgmd, + (uchar**) &opt_ndb_mgmd, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-nodeid", OPT_NDB_NODEID, "Nodeid for this mysqlserver in the cluster.", - (gptr*) &opt_ndb_nodeid, - (gptr*) &opt_ndb_nodeid, + (uchar**) &opt_ndb_nodeid, + (uchar**) &opt_ndb_nodeid, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, "Specify number of autoincrement values that are prefetched.", - (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz, - (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz, + (uchar**) &global_system_variables.ndb_autoincrement_prefetch_sz, + (uchar**) &global_system_variables.ndb_autoincrement_prefetch_sz, 0, GET_ULONG, REQUIRED_ARG, 32, 1, 256, 0, 0, 0}, {"ndb-distribution", OPT_NDB_DISTRIBUTION, "Default distribution for new tables in ndb", - (gptr*) &opt_ndb_distribution, - (gptr*) &opt_ndb_distribution, + (uchar**) &opt_ndb_distribution, + (uchar**) &opt_ndb_distribution, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-force-send", OPT_NDB_FORCE_SEND, "Force send of buffers to ndb immediately without waiting for " "other threads.", - (gptr*) &global_system_variables.ndb_force_send, - (gptr*) &global_system_variables.ndb_force_send, + (uchar**) &global_system_variables.ndb_force_send, + (uchar**) &global_system_variables.ndb_force_send, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_force_send", OPT_NDB_FORCE_SEND, "same as --ndb-force-send.", - (gptr*) &global_system_variables.ndb_force_send, - (gptr*) &global_system_variables.ndb_force_send, + (uchar**) &global_system_variables.ndb_force_send, + (uchar**) &global_system_variables.ndb_force_send, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-extra-logging", OPT_NDB_EXTRA_LOGGING, "Turn on more logging in the error log.", - (gptr*) &ndb_extra_logging, - (gptr*) &ndb_extra_logging, + (uchar**) &ndb_extra_logging, + (uchar**) &ndb_extra_logging, 0, GET_INT, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_NDB_BINLOG {"ndb-report-thresh-binlog-epoch-slip", OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP, @@ -5467,113 +5509,113 @@ master-ssl", "E.g. 3 means that if the difference between what epoch has been received " "from the storage nodes and what has been applied to the binlog is 3 or more, " "a status message will be sent to the cluster log.", - (gptr*) &ndb_report_thresh_binlog_epoch_slip, - (gptr*) &ndb_report_thresh_binlog_epoch_slip, + (uchar**) &ndb_report_thresh_binlog_epoch_slip, + (uchar**) &ndb_report_thresh_binlog_epoch_slip, 0, GET_ULONG, REQUIRED_ARG, 3, 0, 256, 0, 0, 0}, {"ndb-report-thresh-binlog-mem-usage", OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE, "Threshold on percentage of free memory before reporting binlog status. E.g. " "10 means that if amount of available memory for receiving binlog data from " "the storage nodes goes below 10%, " "a status message will be sent to the cluster log.", - (gptr*) &ndb_report_thresh_binlog_mem_usage, - (gptr*) &ndb_report_thresh_binlog_mem_usage, + (uchar**) &ndb_report_thresh_binlog_mem_usage, + (uchar**) &ndb_report_thresh_binlog_mem_usage, 0, GET_ULONG, REQUIRED_ARG, 10, 0, 100, 0, 0, 0}, #endif {"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT, "Use exact records count during query planning and for fast " "select count(*), disable for faster queries.", - (gptr*) &global_system_variables.ndb_use_exact_count, - (gptr*) &global_system_variables.ndb_use_exact_count, + (uchar**) &global_system_variables.ndb_use_exact_count, + (uchar**) &global_system_variables.ndb_use_exact_count, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT, "same as --ndb-use-exact-count.", - (gptr*) &global_system_variables.ndb_use_exact_count, - (gptr*) &global_system_variables.ndb_use_exact_count, + (uchar**) &global_system_variables.ndb_use_exact_count, + (uchar**) &global_system_variables.ndb_use_exact_count, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-use-transactions", OPT_NDB_USE_TRANSACTIONS, "Use transactions for large inserts, if enabled then large " "inserts will be split into several smaller transactions", - (gptr*) &global_system_variables.ndb_use_transactions, - (gptr*) &global_system_variables.ndb_use_transactions, + (uchar**) &global_system_variables.ndb_use_transactions, + (uchar**) &global_system_variables.ndb_use_transactions, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_use_transactions", OPT_NDB_USE_TRANSACTIONS, "same as --ndb-use-transactions.", - (gptr*) &global_system_variables.ndb_use_transactions, - (gptr*) &global_system_variables.ndb_use_transactions, + (uchar**) &global_system_variables.ndb_use_transactions, + (uchar**) &global_system_variables.ndb_use_transactions, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-shm", OPT_NDB_SHM, "Use shared memory connections when available.", - (gptr*) &opt_ndb_shm, - (gptr*) &opt_ndb_shm, + (uchar**) &opt_ndb_shm, + (uchar**) &opt_ndb_shm, 0, GET_BOOL, OPT_ARG, OPT_NDB_SHM_DEFAULT, 0, 0, 0, 0, 0}, {"ndb-optimized-node-selection", OPT_NDB_OPTIMIZED_NODE_SELECTION, "Select nodes for transactions in a more optimal way.", - (gptr*) &opt_ndb_optimized_node_selection, - (gptr*) &opt_ndb_optimized_node_selection, + (uchar**) &opt_ndb_optimized_node_selection, + (uchar**) &opt_ndb_optimized_node_selection, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME, "A dedicated thread is created to, at the given millisecons interval, invalidate the query cache if another MySQL server in the cluster has changed the data in the database.", - (gptr*) &opt_ndb_cache_check_time, (gptr*) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &opt_ndb_cache_check_time, (uchar**) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG, 0, 0, LONG_TIMEOUT, 0, 1, 0}, {"ndb-index-stat-enable", OPT_NDB_INDEX_STAT_ENABLE, "Use ndb index statistics in query optimization.", - (gptr*) &global_system_variables.ndb_index_stat_enable, - (gptr*) &max_system_variables.ndb_index_stat_enable, + (uchar**) &global_system_variables.ndb_index_stat_enable, + (uchar**) &max_system_variables.ndb_index_stat_enable, 0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 0, 0}, #endif {"ndb-use-copying-alter-table", OPT_NDB_USE_COPYING_ALTER_TABLE, "Force ndbcluster to always copy tables at alter table (should only be used if on-line alter table fails).", - (gptr*) &global_system_variables.ndb_use_copying_alter_table, - (gptr*) &global_system_variables.ndb_use_copying_alter_table, + (uchar**) &global_system_variables.ndb_use_copying_alter_table, + (uchar**) &global_system_variables.ndb_use_copying_alter_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"new", 'n', "Use very new possible 'unsafe' functions.", - (gptr*) &global_system_variables.new_mode, - (gptr*) &max_system_variables.new_mode, + (uchar**) &global_system_variables.new_mode, + (uchar**) &max_system_variables.new_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef NOT_YET {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types.", - (gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, + (uchar**) &opt_no_mix_types, (uchar**) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"old-alter-table", OPT_OLD_ALTER_TABLE, "Use old, non-optimized alter table.", - (gptr*) &global_system_variables.old_alter_table, - (gptr*) &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG, + (uchar**) &global_system_variables.old_alter_table, + (uchar**) &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).", - (gptr*) &global_system_variables.old_passwords, - (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, + (uchar**) &global_system_variables.old_passwords, + (uchar**) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"one-thread", OPT_ONE_THREAD, "(deprecated): Only use one thread (for debugging under Linux). Use thread-handling=no-threads instead", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS, "Enable old-style user limits (before 5.0.3 user resources were counted per each user+host vs. per account)", - (gptr*) &opt_old_style_user_limits, (gptr*) &opt_old_style_user_limits, + (uchar**) &opt_old_style_user_limits, (uchar**) &opt_old_style_user_limits, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.", - (gptr*) &pidfile_name_ptr, (gptr*) &pidfile_name_ptr, 0, GET_STR, + (uchar**) &pidfile_name_ptr, (uchar**) &pidfile_name_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"port", 'P', "Port number to use for connection.", (gptr*) &mysqld_port, - (gptr*) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"port", 'P', "Port number to use for connection.", (uchar**) &mysqld_port, + (uchar**) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT, "Maximum time in seconds to wait for the port to become free. " - "(Default: no wait)", (gptr*) &mysqld_port_timeout, - (gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "(Default: no wait)", (uchar**) &mysqld_port_timeout, + (uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log", OPT_RELAY_LOG, "The location and name to use for relay logs.", - (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0, + (uchar**) &opt_relay_logname, (uchar**) &opt_relay_logname, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log-index", OPT_RELAY_LOG_INDEX, "The location and name to use for the file that keeps a list of the last \ relay logs.", - (gptr*) &opt_relaylog_index_name, (gptr*) &opt_relaylog_index_name, 0, + (uchar**) &opt_relaylog_index_name, (uchar**) &opt_relaylog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "The location and name of the file that remembers where the SQL replication \ thread is in the relay logs.", - (gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR, + (uchar**) &relay_log_info_file, (uchar**) &relay_log_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-db", OPT_REPLICATE_DO_DB, "Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.", @@ -5595,8 +5637,8 @@ thread is in the relay logs.", "In replication, if set to 1, do not skip events having our server id. \ Default value is 0 (to break infinite loops in circular replication). \ Can't be set to 1 if --log-slave-updates is used.", - (gptr*) &replicate_same_server_id, - (gptr*) &replicate_same_server_id, + (uchar**) &replicate_same_server_id, + (uchar**) &replicate_same_server_id, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE, @@ -5608,19 +5650,19 @@ Can't be set to 1 if --log-slave-updates is used.", // In replication, we may need to tell the other servers how to connect {"report-host", OPT_REPORT_HOST, "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.", - (gptr*) &report_host, (gptr*) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, + (uchar**) &report_host, (uchar**) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"report-password", OPT_REPORT_PASSWORD, "Undocumented.", - (gptr*) &report_password, (gptr*) &report_password, 0, GET_STR, + (uchar**) &report_password, (uchar**) &report_password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"report-port", OPT_REPORT_PORT, "Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset.", - (gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG, + (uchar**) &report_port, (uchar**) &report_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"report-user", OPT_REPORT_USER, "Undocumented.", (gptr*) &report_user, - (gptr*) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"report-user", OPT_REPORT_USER, "Undocumented.", (uchar**) &report_user, + (uchar**) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented.", - (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG, + (uchar**) &rpl_recovery_rank, (uchar**) &rpl_recovery_rank, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5631,43 +5673,43 @@ Can't be set to 1 if --log-slave-updates is used.", #endif {"safe-user-create", OPT_SAFE_USER_CREATE, "Don't allow new user creation by the user who has no write privileges to the mysql.user table.", - (gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL, + (uchar**) &opt_safe_user_create, (uchar**) &opt_safe_user_create, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT, "Simulate memory shortage when compiled with the --with-debug=full option.", 0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.", - (gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG, + (uchar**) &opt_secure_auth, (uchar**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, my_bool(0), 0, 0, 0, 0, 0}, {"secure-file-priv", OPT_SECURE_FILE_PRIV, "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory", - (gptr*) &opt_secure_file_priv, (gptr*) &opt_secure_file_priv, 0, + (uchar**) &opt_secure_file_priv, (uchar**) &opt_secure_file_priv, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-id", OPT_SERVER_ID, "Uniquely identifies the server instance in the community of replication partners.", - (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, + (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory", OPT_ENABLE_SHARED_MEMORY, - "Enable the shared memory.",(gptr*) &opt_enable_shared_memory, (gptr*) &opt_enable_shared_memory, + "Enable the shared memory.",(uchar**) &opt_enable_shared_memory, (uchar**) &opt_enable_shared_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #ifdef HAVE_SMEM {"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, "Show user and password in SHOW SLAVE HOSTS on this master", - (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, + (uchar**) &opt_show_slave_auth_info, (uchar**) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DISABLE_GRANT_OPTIONS {"skip-grant-tables", OPT_SKIP_GRANT, "Start without grant tables. This gives all users FULL ACCESS to all tables!", - (gptr*) &opt_noacl, (gptr*) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + (uchar**) &opt_noacl, (uchar**) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0, @@ -5694,8 +5736,8 @@ Can't be set to 1 if --log-slave-updates is used.", "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-slave-start", OPT_SKIP_SLAVE_START, - "If set, slave is not autostarted.", (gptr*) &opt_skip_slave_start, - (gptr*) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "If set, slave is not autostarted.", (uchar**) &opt_skip_slave_start, + (uchar**) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-stack-trace", OPT_SKIP_STACK_TRACE, "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5708,23 +5750,23 @@ Can't be set to 1 if --log-slave-updates is used.", {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "The location where the slave should put its temporary files when \ replicating a LOAD DATA INFILE command.", - (gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC, + (uchar**) &slave_load_tmpdir, (uchar**) &slave_load_tmpdir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS, "Tells the slave thread to continue replication when a query returns an error from the provided list.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"slow-query-log", OPT_SLOW_LOG, - "Enable|disable slow query log", (gptr*) &opt_slow_log, - (gptr*) &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Enable|disable slow query log", (uchar**) &opt_slow_log, + (uchar**) &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"socket", OPT_SOCKET, "Socket file to use for connection.", - (gptr*) &mysqld_unix_port, (gptr*) &mysqld_unix_port, 0, GET_STR, + (uchar**) &mysqld_unix_port, (uchar**) &mysqld_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL, "Option used by mysql-test for debugging and testing of replication.", - (gptr*) &opt_sporadic_binlog_dump_fail, - (gptr*) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + (uchar**) &opt_sporadic_binlog_dump_fail, + (uchar**) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME, @@ -5733,7 +5775,7 @@ log and this option does nothing anymore.", 0, 0, 0, GET_DISABLED, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sql-mode", OPT_SQL_MODE, "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", - (gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, + (uchar**) &sql_mode_str, (uchar**) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL #include "sslopt-longopts.h" @@ -5744,7 +5786,7 @@ log and this option does nothing anymore.", NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"symbolic-links", 's', "Enable symbolic link support.", - (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG, + (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, /* The system call realpath() produces warnings under valgrind and purify. These are not suppressed: instead we disable symlinks @@ -5753,19 +5795,19 @@ log and this option does nothing anymore.", IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"sysdate-is-now", OPT_SYSDATE_IS_NOW, "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. Since 5.0, SYSDATE() returns a `dynamic' value different for different invocations, even within the same statement.", - (gptr*) &global_system_variables.sysdate_is_now, + (uchar**) &global_system_variables.sysdate_is_now, 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER, "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.", - (gptr*) &opt_tc_heuristic_recover, (gptr*) &opt_tc_heuristic_recover, + (uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"temp-pool", OPT_TEMP_POOL, "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.", - (gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, + (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"timed_mutexes", OPT_TIMED_MUTEXES, "Specify whether to time mutexes (only InnoDB mutexes are currently supported)", - (gptr*) &timed_mutexes, (gptr*) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, + (uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files. Several paths may be specified, separated by a " @@ -5775,83 +5817,83 @@ log and this option does nothing anymore.", "colon (:)" #endif ", in this case they are used in a round-robin fashion.", - (gptr*) &opt_mysql_tmpdir, - (gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (uchar**) &opt_mysql_tmpdir, + (uchar**) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"transaction-isolation", OPT_TX_ISOLATION, "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", - (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG, + (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Used with --help option for detailed help", - (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"warnings", 'W', "Deprecated; use --log-warnings instead.", - (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, + (uchar**) &global_system_variables.log_warnings, + (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, 0, 0, 0}, { "back_log", OPT_BACK_LOG, "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", - (gptr*) &back_log, (gptr*) &back_log, 0, GET_ULONG, + (uchar**) &back_log, (uchar**) &back_log, 0, GET_ULONG, REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 }, {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE, "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.", - (gptr*) &binlog_cache_size, (gptr*) &binlog_cache_size, 0, GET_ULONG, + (uchar**) &binlog_cache_size, (uchar**) &binlog_cache_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE, "Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!", - (gptr*) &global_system_variables.bulk_insert_buff_size, - (gptr*) &max_system_variables.bulk_insert_buff_size, + (uchar**) &global_system_variables.bulk_insert_buff_size, + (uchar**) &max_system_variables.bulk_insert_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", - (gptr*) &connect_timeout, (gptr*) &connect_timeout, + (uchar**) &connect_timeout, (uchar**) &connect_timeout, 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 }, { "date_format", OPT_DATE_FORMAT, "The DATE format (For future).", - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "datetime_format", OPT_DATETIME_FORMAT, "The DATETIME/TIMESTAMP format (for future).", - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "default_week_format", OPT_DEFAULT_WEEK_FORMAT, "The default week format used by WEEK() functions.", - (gptr*) &global_system_variables.default_week_format, - (gptr*) &max_system_variables.default_week_format, + (uchar**) &global_system_variables.default_week_format, + (uchar**) &max_system_variables.default_week_format, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT, "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.", - (gptr*) &delayed_insert_limit, (gptr*) &delayed_insert_limit, 0, GET_ULONG, + (uchar**) &delayed_insert_limit, (uchar**) &delayed_insert_limit, 0, GET_ULONG, REQUIRED_ARG, DELAYED_LIMIT, 1, ~0L, 0, 1, 0}, {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.", - (gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0, + (uchar**) &delayed_insert_timeout, (uchar**) &delayed_insert_timeout, 0, GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE, "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.", - (gptr*) &delayed_queue_size, (gptr*) &delayed_queue_size, 0, GET_ULONG, + (uchar**) &delayed_queue_size, (uchar**) &delayed_queue_size, 0, GET_ULONG, REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1, 0}, {"div_precision_increment", OPT_DIV_PRECINCREMENT, "Precision of the result of '/' operator will be increased on that value.", - (gptr*) &global_system_variables.div_precincrement, - (gptr*) &max_system_variables.div_precincrement, 0, GET_ULONG, + (uchar**) &global_system_variables.div_precincrement, + (uchar**) &max_system_variables.div_precincrement, 0, GET_ULONG, REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, "If non-zero, binary logs will be purged after expire_logs_days " "days; possible purges happen at startup and at binary log rotation.", - (gptr*) &expire_logs_days, - (gptr*) &expire_logs_days, 0, GET_ULONG, + (uchar**) &expire_logs_days, + (uchar**) &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, { "flush_time", OPT_FLUSH_TIME, "A dedicated thread is created to flush all tables at the given interval.", - (gptr*) &flush_time, (gptr*) &flush_time, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &flush_time, (uchar**) &flush_time, 0, GET_ULONG, REQUIRED_ARG, FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0}, { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX, "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE)", @@ -5859,70 +5901,70 @@ log and this option does nothing anymore.", REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, "The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_ULONG, + (uchar**) &ft_max_word_len, (uchar**) &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, "The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_ULONG, + (uchar**) &ft_min_word_len, (uchar**) &ft_min_word_len, 0, GET_ULONG, REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_query_expansion_limit", OPT_FT_QUERY_EXPANSION_LIMIT, "Number of best matches to use for query expansion", - (gptr*) &ft_query_expansion_limit, (gptr*) &ft_query_expansion_limit, 0, GET_ULONG, + (uchar**) &ft_query_expansion_limit, (uchar**) &ft_query_expansion_limit, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 1000, 0, 1, 0}, { "ft_stopword_file", OPT_FT_STOPWORD_FILE, "Use stopwords from this file instead of built-in list.", - (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, + (uchar**) &ft_stopword_file, (uchar**) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN, "The maximum length of the result of function group_concat.", - (gptr*) &global_system_variables.group_concat_max_len, - (gptr*) &max_system_variables.group_concat_max_len, 0, GET_ULONG, + (uchar**) &global_system_variables.group_concat_max_len, + (uchar**) &max_system_variables.group_concat_max_len, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0}, {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, "The number of seconds the server waits for activity on an interactive connection before closing it.", - (gptr*) &global_system_variables.net_interactive_timeout, - (gptr*) &max_system_variables.net_interactive_timeout, 0, + (uchar**) &global_system_variables.net_interactive_timeout, + (uchar**) &max_system_variables.net_interactive_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"join_buffer_size", OPT_JOIN_BUFF_SIZE, "The size of the buffer that is used for full joins.", - (gptr*) &global_system_variables.join_buff_size, - (gptr*) &max_system_variables.join_buff_size, 0, GET_ULONG, + (uchar**) &global_system_variables.join_buff_size, + (uchar**) &max_system_variables.join_buff_size, 0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", - (gptr*) &dflt_key_cache_var.param_buff_size, - (gptr*) 0, + (uchar**) &dflt_key_cache_var.param_buff_size, + (uchar**) 0, 0, (GET_ULL | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache", - (gptr*) &dflt_key_cache_var.param_age_threshold, - (gptr*) 0, + (uchar**) &dflt_key_cache_var.param_age_threshold, + (uchar**) 0, 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, 300, 100, ~0L, 0, 100, 0}, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "The default size of key cache blocks", - (gptr*) &dflt_key_cache_var.param_block_size, - (gptr*) 0, + (uchar**) &dflt_key_cache_var.param_block_size, + (uchar**) 0, 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0}, + KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0}, {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT, "The minimum percentage of warm blocks in key cache", - (gptr*) &dflt_key_cache_var.param_division_limit, - (gptr*) 0, + (uchar**) &dflt_key_cache_var.param_division_limit, + (uchar**) 0, 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, "Log all queries that have taken more than long_query_time seconds to execute to file.", - (gptr*) &global_system_variables.long_query_time, - (gptr*) &max_system_variables.long_query_time, 0, GET_ULONG, + (uchar**) &global_system_variables.long_query_time, + (uchar**) &max_system_variables.long_query_time, 0, GET_ULONG, REQUIRED_ARG, 10, 1, LONG_TIMEOUT, 0, 1, 0}, {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES, "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive. Should be set to 2 if you are using a case insensitive file system", - (gptr*) &lower_case_table_names, - (gptr*) &lower_case_table_names, 0, GET_UINT, OPT_ARG, + (uchar**) &lower_case_table_names, + (uchar**) &lower_case_table_names, 0, GET_UINT, OPT_ARG, #ifdef FN_NO_CASE_SENCE 1 #else @@ -5931,356 +5973,356 @@ log and this option does nothing anymore.", , 0, 2, 0, 1, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "Max packetlength to send/receive from to server.", - (gptr*) &global_system_variables.max_allowed_packet, - (gptr*) &max_system_variables.max_allowed_packet, 0, GET_ULONG, + (uchar**) &global_system_variables.max_allowed_packet, + (uchar**) &max_system_variables.max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE, "Can be used to restrict the total size used to cache a multi-transaction query.", - (gptr*) &max_binlog_cache_size, (gptr*) &max_binlog_cache_size, 0, + (uchar**) &max_binlog_cache_size, (uchar**) &max_binlog_cache_size, 0, GET_ULONG, REQUIRED_ARG, ~0L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, {"max_binlog_size", OPT_MAX_BINLOG_SIZE, "Binary log will be rotated automatically when the size exceeds this \ value. Will also apply to relay logs if max_relay_log_size is 0. \ The minimum value for this variable is 4096.", - (gptr*) &max_binlog_size, (gptr*) &max_binlog_size, 0, GET_ULONG, + (uchar**) &max_binlog_size, (uchar**) &max_binlog_size, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L*1024L, IO_SIZE, 1024*1024L*1024L, 0, IO_SIZE, 0}, {"max_connect_errors", OPT_MAX_CONNECT_ERRORS, "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.", - (gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG, + (uchar**) &max_connect_errors, (uchar**) &max_connect_errors, 0, GET_ULONG, REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0}, // Default max_connections of 151 is larger than Apache's default max // children, to avoid "too many connections" error in a common setup {"max_connections", OPT_MAX_CONNECTIONS, - "The number of simultaneous clients allowed.", (gptr*) &max_connections, - (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, + "The number of simultaneous clients allowed.", (uchar**) &max_connections, + (uchar**) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, 0}, {"max_delayed_threads", OPT_MAX_DELAYED_THREADS, "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.", - (gptr*) &global_system_variables.max_insert_delayed_threads, - (gptr*) &max_system_variables.max_insert_delayed_threads, + (uchar**) &global_system_variables.max_insert_delayed_threads, + (uchar**) &max_system_variables.max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, {"max_error_count", OPT_MAX_ERROR_COUNT, "Max number of errors/warnings to store for a statement.", - (gptr*) &global_system_variables.max_error_count, - (gptr*) &max_system_variables.max_error_count, + (uchar**) &global_system_variables.max_error_count, + (uchar**) &max_system_variables.max_error_count, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0}, {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, "Don't allow creation of heap tables bigger than this.", - (gptr*) &global_system_variables.max_heap_table_size, - (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULL, + (uchar**) &global_system_variables.max_heap_table_size, + (uchar**) &max_system_variables.max_heap_table_size, 0, GET_ULL, REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE, MALLOC_OVERHEAD, 1024, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "Joins that are probably going to read more than max_join_size records return an error.", - (gptr*) &global_system_variables.max_join_size, - (gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, + (uchar**) &global_system_variables.max_join_size, + (uchar**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA, "Max number of bytes in sorted records.", - (gptr*) &global_system_variables.max_length_for_sort_data, - (gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, + (uchar**) &global_system_variables.max_length_for_sort_data, + (uchar**) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT, "Maximum number of prepared statements in the server.", - (gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count, + (uchar**) &max_prepared_stmt_count, (uchar**) &max_prepared_stmt_count, 0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0}, {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE, "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.", - (gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG, + (uchar**) &max_relay_log_size, (uchar**) &max_relay_log_size, 0, GET_ULONG, REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0}, { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY, "Limit assumed max number of seeks when looking up rows based on a key", - (gptr*) &global_system_variables.max_seeks_for_key, - (gptr*) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, + (uchar**) &global_system_variables.max_seeks_for_key, + (uchar**) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0 }, {"max_sort_length", OPT_MAX_SORT_LENGTH, "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", - (gptr*) &global_system_variables.max_sort_length, - (gptr*) &max_system_variables.max_sort_length, 0, GET_ULONG, + (uchar**) &global_system_variables.max_sort_length, + (uchar**) &max_system_variables.max_sort_length, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH, "Maximum stored procedure recursion depth. (discussed with docs).", - (gptr*) &global_system_variables.max_sp_recursion_depth, - (gptr*) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, + (uchar**) &global_system_variables.max_sp_recursion_depth, + (uchar**) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, OPT_ARG, 0, 0, 255, 0, 1, 0 }, {"max_tmp_tables", OPT_MAX_TMP_TABLES, "Maximum number of temporary tables a client can keep open at a time.", - (gptr*) &global_system_variables.max_tmp_tables, - (gptr*) &max_system_variables.max_tmp_tables, 0, GET_ULONG, + (uchar**) &global_system_variables.max_tmp_tables, + (uchar**) &max_system_variables.max_tmp_tables, 0, GET_ULONG, REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0}, {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", - (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_UINT, + (uchar**) &max_user_connections, (uchar**) &max_user_connections, 0, GET_UINT, REQUIRED_ARG, 0, 1, ~0, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", - (gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG, + (uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, {"multi_range_count", OPT_MULTI_RANGE_COUNT, "Number of key ranges to request at once.", - (gptr*) &global_system_variables.multi_range_count, - (gptr*) &max_system_variables.multi_range_count, 0, + (uchar**) &global_system_variables.multi_range_count, + (uchar**) &max_system_variables.multi_range_count, 0, GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "Block size to be used for MyISAM index pages.", - (gptr*) &opt_myisam_block_size, - (gptr*) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &opt_myisam_block_size, + (uchar**) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, {"myisam_data_pointer_size", OPT_MYISAM_DATA_POINTER_SIZE, "Default pointer size to be used for MyISAM tables.", - (gptr*) &myisam_data_pointer_size, - (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &myisam_data_pointer_size, + (uchar**) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, 6, 2, 7, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, "Deprecated option", - (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, - (gptr*) &max_system_variables.myisam_max_extra_sort_file_size, + (uchar**) &global_system_variables.myisam_max_extra_sort_file_size, + (uchar**) &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, "Don't use the fast sort index method to created index if the temporary file would get bigger than this.", - (gptr*) &global_system_variables.myisam_max_sort_file_size, - (gptr*) &max_system_variables.myisam_max_sort_file_size, 0, + (uchar**) &global_system_variables.myisam_max_sort_file_size, + (uchar**) &max_system_variables.myisam_max_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, 0, 1024*1024, 0}, {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", - (gptr*) &global_system_variables.myisam_repair_threads, - (gptr*) &max_system_variables.myisam_repair_threads, 0, + (uchar**) &global_system_variables.myisam_repair_threads, + (uchar**) &max_system_variables.myisam_repair_threads, 0, GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0}, {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", - (gptr*) &global_system_variables.myisam_sort_buff_size, - (gptr*) &max_system_variables.myisam_sort_buff_size, 0, + (uchar**) &global_system_variables.myisam_sort_buff_size, + (uchar**) &max_system_variables.myisam_sort_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, {"myisam_use_mmap", OPT_MYISAM_USE_MMAP, "Use memory mapping for reading and writing MyISAM tables", - (gptr*) &opt_myisam_use_mmap, - (gptr*) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0, + (uchar**) &opt_myisam_use_mmap, + (uchar**) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"myisam_stats_method", OPT_MYISAM_STATS_METHOD, "Specifies how MyISAM index statistics collection code should threat NULLs. " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", - (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, + (uchar**) &myisam_stats_method_str, (uchar**) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "Buffer length for TCP/IP and socket communication.", - (gptr*) &global_system_variables.net_buffer_length, - (gptr*) &max_system_variables.net_buffer_length, 0, GET_ULONG, + (uchar**) &global_system_variables.net_buffer_length, + (uchar**) &max_system_variables.net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0}, {"net_read_timeout", OPT_NET_READ_TIMEOUT, "Number of seconds to wait for more data from a connection before aborting the read.", - (gptr*) &global_system_variables.net_read_timeout, - (gptr*) &max_system_variables.net_read_timeout, 0, GET_ULONG, + (uchar**) &global_system_variables.net_read_timeout, + (uchar**) &max_system_variables.net_read_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"net_retry_count", OPT_NET_RETRY_COUNT, "If a read on a communication port is interrupted, retry this many times before giving up.", - (gptr*) &global_system_variables.net_retry_count, - (gptr*) &max_system_variables.net_retry_count,0, + (uchar**) &global_system_variables.net_retry_count, + (uchar**) &max_system_variables.net_retry_count,0, GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1, 0}, {"net_write_timeout", OPT_NET_WRITE_TIMEOUT, "Number of seconds to wait for a block to be written to a connection before aborting the write.", - (gptr*) &global_system_variables.net_write_timeout, - (gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG, + (uchar**) &global_system_variables.net_write_timeout, + (uchar**) &max_system_variables.net_write_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, { "old", OPT_OLD_MODE, "Use compatible behavior.", - (gptr*) &global_system_variables.old_mode, - (gptr*) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG, + (uchar**) &global_system_variables.old_mode, + (uchar**) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"open_files_limit", OPT_OPEN_FILES_LIMIT, "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", - (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, + (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0}, {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL, "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows.", - (gptr*) &global_system_variables.optimizer_prune_level, - (gptr*) &max_system_variables.optimizer_prune_level, + (uchar**) &global_system_variables.optimizer_prune_level, + (uchar**) &max_system_variables.optimizer_prune_level, 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0}, {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH, "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).", - (gptr*) &global_system_variables.optimizer_search_depth, - (gptr*) &max_system_variables.optimizer_search_depth, + (uchar**) &global_system_variables.optimizer_search_depth, + (uchar**) &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, {"plugin_dir", OPT_PLUGIN_DIR, "Directory for plugins.", - (gptr*) &opt_plugin_dir_ptr, (gptr*) &opt_plugin_dir_ptr, 0, + (uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"plugin_load", OPT_PLUGIN_LOAD, "Optional colon separated list of plugins to load, where each plugin is " "identified by name and path to library seperated by an equals.", - (gptr*) &opt_plugin_load, (gptr*) &opt_plugin_load, 0, + (uchar**) &opt_plugin_load, (uchar**) &opt_plugin_load, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, + {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes", - (gptr*) &global_system_variables.preload_buff_size, - (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG, + (uchar**) &global_system_variables.preload_buff_size, + (uchar**) &max_system_variables.preload_buff_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0}, {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE, "Allocation block size for query parsing and execution", - (gptr*) &global_system_variables.query_alloc_block_size, - (gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, + (uchar**) &global_system_variables.query_alloc_block_size, + (uchar**) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", - (gptr*) &query_cache_limit, (gptr*) &query_cache_limit, 0, GET_ULONG, + (uchar**) &query_cache_limit, (uchar**) &query_cache_limit, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L, 0, (longlong) ULONG_MAX, 0, 1, 0}, {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT, "minimal size of unit in wich space for results is allocated (last unit will be trimed after writing all result data.", - (gptr*) &query_cache_min_res_unit, (gptr*) &query_cache_min_res_unit, + (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE, 0, (longlong) ULONG_MAX, 0, 1, 0}, #endif /*HAVE_QUERY_CACHE*/ {"query_cache_size", OPT_QUERY_CACHE_SIZE, "The memory allocated to store results from old queries.", - (gptr*) &query_cache_size, (gptr*) &query_cache_size, 0, GET_ULONG, + (uchar**) &query_cache_size, (uchar**) &query_cache_size, 0, GET_ULONG, REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_type", OPT_QUERY_CACHE_TYPE, "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.", - (gptr*) &global_system_variables.query_cache_type, - (gptr*) &max_system_variables.query_cache_type, + (uchar**) &global_system_variables.query_cache_type, + (uchar**) &max_system_variables.query_cache_type, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE, "Invalidate queries in query cache on LOCK for write", - (gptr*) &global_system_variables.query_cache_wlock_invalidate, - (gptr*) &max_system_variables.query_cache_wlock_invalidate, + (uchar**) &global_system_variables.query_cache_wlock_invalidate, + (uchar**) &max_system_variables.query_cache_wlock_invalidate, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, #endif /*HAVE_QUERY_CACHE*/ {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE, "Persistent buffer for query parsing and execution", - (gptr*) &global_system_variables.query_prealloc_size, - (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG, + (uchar**) &global_system_variables.query_prealloc_size, + (uchar**) &max_system_variables.query_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE, ~0L, 0, 1024, 0}, {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, "Allocation block size for storing ranges during optimization", - (gptr*) &global_system_variables.range_alloc_block_size, - (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, + (uchar**) &global_system_variables.range_alloc_block_size, + (uchar**) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0}, {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", - (gptr*) &global_system_variables.read_buff_size, - (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, + (uchar**) &global_system_variables.read_buff_size, + (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, {"read_only", OPT_READONLY, "Make all non-temporary tables read-only, with the exception for replication (slave) threads and users with the SUPER privilege", - (gptr*) &opt_readonly, - (gptr*) &opt_readonly, + (uchar**) &opt_readonly, + (uchar**) &opt_readonly, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER, "When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks. If not set, then it's set to the value of record_buffer.", - (gptr*) &global_system_variables.read_rnd_buff_size, - (gptr*) &max_system_variables.read_rnd_buff_size, 0, + (uchar**) &global_system_variables.read_rnd_buff_size, + (uchar**) &max_system_variables.read_rnd_buff_size, 0, GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, {"record_buffer", OPT_RECORD_BUFFER, "Alias for read_buffer_size", - (gptr*) &global_system_variables.read_buff_size, - (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, + (uchar**) &global_system_variables.read_buff_size, + (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, #ifdef HAVE_REPLICATION {"relay_log_purge", OPT_RELAY_LOG_PURGE, "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.", - (gptr*) &relay_log_purge, - (gptr*) &relay_log_purge, 0, GET_BOOL, NO_ARG, + (uchar**) &relay_log_purge, + (uchar**) &relay_log_purge, 0, GET_BOOL, NO_ARG, 1, 0, 1, 0, 1, 0}, {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT, "Maximum space to use for all relay logs.", - (gptr*) &relay_log_space_limit, - (gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, + (uchar**) &relay_log_space_limit, + (uchar**) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL, "Use compression on master/slave protocol.", - (gptr*) &opt_slave_compressed_protocol, - (gptr*) &opt_slave_compressed_protocol, + (uchar**) &opt_slave_compressed_protocol, + (uchar**) &opt_slave_compressed_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT, "Number of seconds to wait for more data from a master/slave connection before aborting the read.", - (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, + (uchar**) &slave_net_timeout, (uchar**) &slave_net_timeout, 0, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES, "Number of times the slave SQL thread will retry a transaction in case " "it failed with a deadlock or elapsed lock wait timeout, " "before giving up and stopping.", - (gptr*) &slave_trans_retries, (gptr*) &slave_trans_retries, 0, + (uchar**) &slave_trans_retries, (uchar**) &slave_trans_retries, 0, GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, #endif /* HAVE_REPLICATION */ {"slow_launch_time", OPT_SLOW_LAUNCH_TIME, "If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.", - (gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG, + (uchar**) &slow_launch_time, (uchar**) &slow_launch_time, 0, GET_ULONG, REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0}, {"sort_buffer_size", OPT_SORT_BUFFER, "Each thread that needs to do a sort allocates a buffer of this size.", - (gptr*) &global_system_variables.sortbuff_size, - (gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &global_system_variables.sortbuff_size, + (uchar**) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1, 0}, {"sync-binlog", OPT_SYNC_BINLOG, "Synchronously flush binary log to disk after every #th event. " "Use 0 (default) to disable synchronous flushing.", - (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG, + (uchar**) &sync_binlog_period, (uchar**) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", - (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, + (uchar**) &opt_sync_frm, (uchar**) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"table_cache", OPT_TABLE_OPEN_CACHE, "Deprecated; use --table_open_cache instead.", - (gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG, + (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, {"table_definition_cache", OPT_TABLE_DEF_CACHE, "The number of cached table definitions.", - (gptr*) &table_def_size, (gptr*) &table_def_size, + (uchar**) &table_def_size, (uchar**) &table_def_size, 0, GET_ULONG, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0}, {"table_open_cache", OPT_TABLE_OPEN_CACHE, "The number of cached open tables.", - (gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG, + (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in seconds to wait for a table level lock before returning an " "error. Used only if the connection has active cursors.", - (gptr*) &table_lock_wait_timeout, (gptr*) &table_lock_wait_timeout, + (uchar**) &table_lock_wait_timeout, (uchar**) &table_lock_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0}, {"thread_cache_size", OPT_THREAD_CACHE_SIZE, "How many threads we should keep in a cache for reuse.", - (gptr*) &thread_cache_size, (gptr*) &thread_cache_size, 0, GET_ULONG, + (uchar**) &thread_cache_size, (uchar**) &thread_cache_size, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 16384, 0, 1, 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", - (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_ULONG, REQUIRED_ARG, + (uchar**) &concurrency, (uchar**) &concurrency, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0}, #if HAVE_POOL_OF_THREADS == 1 {"thread_pool_size", OPT_THREAD_CACHE_SIZE, "How many threads we should create to handle query requests in case of 'thread_handling=pool-of-threads'", - (gptr*) &thread_pool_size, (gptr*) &thread_pool_size, 0, GET_ULONG, + (uchar**) &thread_pool_size, (uchar**) &thread_pool_size, 0, GET_ULONG, REQUIRED_ARG, 20, 1, 16384, 0, 1, 0}, #endif {"thread_stack", OPT_THREAD_STACK, - "The stack size for each thread.", (gptr*) &thread_stack, - (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, + "The stack size for each thread.", (uchar**) &thread_stack, + (uchar**) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, 1024L*128L, ~0L, 0, 1024, 0}, { "time_format", OPT_TIME_FORMAT, "The TIME format (for future).", - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], - (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], + (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmp_table_size", OPT_TMP_TABLE_SIZE, "If an in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM table.", - (gptr*) &global_system_variables.tmp_table_size, - (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULL, + (uchar**) &global_system_variables.tmp_table_size, + (uchar**) &max_system_variables.tmp_table_size, 0, GET_ULL, REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for various transaction-related structures", - (gptr*) &global_system_variables.trans_alloc_block_size, - (gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, + (uchar**) &global_system_variables.trans_alloc_block_size, + (uchar**) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, "Persistent buffer for various transaction-related structures", - (gptr*) &global_system_variables.trans_prealloc_size, - (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, + (uchar**) &global_system_variables.trans_prealloc_size, + (uchar**) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, {"thread_handling", OPT_THREAD_HANDLING, "Define threads usage for handling queries: " @@ -6288,13 +6330,13 @@ The minimum value for this variable is 4096.", 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT, "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).", - (gptr*) &global_system_variables.updatable_views_with_limit, - (gptr*) &max_system_variables.updatable_views_with_limit, + (uchar**) &global_system_variables.updatable_views_with_limit, + (uchar**) &max_system_variables.updatable_views_with_limit, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0}, {"wait_timeout", OPT_WAIT_TIMEOUT, "The number of seconds the server waits for activity on a connection before closing it.", - (gptr*) &global_system_variables.net_wait_timeout, - (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, + (uchar**) &global_system_variables.net_wait_timeout, + (uchar**) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -6657,8 +6699,8 @@ SHOW_VAR status_vars[]= { {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG}, {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG}, {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG}, - {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONG_STATUS}, - {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONG_STATUS}, + {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS}, + {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, {"Com_admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS}, {"Com_alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS}, {"Com_alter_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS}, @@ -6993,7 +7035,7 @@ static void mysql_init_variables(void) prepared_stmt_count= 0; errmesg= 0; mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; - bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); + bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); bzero((char *) &global_status_var, sizeof(global_status_var)); opt_large_pages= 0; key_map_full.set_all(); @@ -7040,6 +7082,7 @@ static void mysql_init_variables(void) sizeof(mysql_real_data_home)-1); mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here mysql_data_home_buff[1]=0; + mysql_data_home_len= 2; /* Replication parameters */ master_user= (char*) "test"; @@ -7201,6 +7244,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1); /* Correct pointer set by my_getopt (for embedded library) */ mysql_data_home= mysql_real_data_home; + mysql_data_home_len= strlen(mysql_data_home); break; case 'u': if (!mysqld_user || !strcmp(mysqld_user, argument)) @@ -7641,7 +7685,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; } case OPT_FT_BOOLEAN_SYNTAX: - if (ft_boolean_check_syntax_string((byte*) argument)) + if (ft_boolean_check_syntax_string((uchar*) argument)) { fprintf(stderr, "Invalid ft-boolean-syntax string: %s\n", argument); exit(1); @@ -7662,7 +7706,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } /* Initiates DEBUG - but no debugging here ! */ -static gptr * +static uchar* * mysql_getopt_value(const char *keyname, uint key_length, const struct my_option *option) { @@ -7677,13 +7721,13 @@ mysql_getopt_value(const char *keyname, uint key_length, exit(1); switch (option->id) { case OPT_KEY_BUFFER_SIZE: - return (gptr*) &key_cache->param_buff_size; + return (uchar**) &key_cache->param_buff_size; case OPT_KEY_CACHE_BLOCK_SIZE: - return (gptr*) &key_cache->param_block_size; + return (uchar**) &key_cache->param_block_size; case OPT_KEY_CACHE_DIVISION_LIMIT: - return (gptr*) &key_cache->param_division_limit; + return (uchar**) &key_cache->param_division_limit; case OPT_KEY_CACHE_AGE_THRESHOLD: - return (gptr*) &key_cache->param_age_threshold; + return (uchar**) &key_cache->param_age_threshold; } } } @@ -7835,7 +7879,7 @@ static char *get_relative_path(const char *path) */ bool -fn_format_relative_to_data_home(my_string to, const char *name, +fn_format_relative_to_data_home(char * to, const char *name, const char *dir, const char *extension) { char tmp_path[FN_REFLEN]; @@ -7953,7 +7997,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib) found=0; found_end= 0; - pos=(my_string) x; + pos=(char *) x; while (*pos == ' ') pos++; found_end= *pos == 0; while (!found_end) @@ -8050,7 +8094,7 @@ static void create_pid_file() char buff[21], *end; end= int10_to_str((long) getpid(), buff, 10); *end++= '\n'; - if (!my_write(file, (byte*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP))) + if (!my_write(file, (uchar*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP))) { (void) my_close(file, MYF(0)); return; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 719e2ee0d3c..959418df87b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -108,7 +108,7 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length); #define TEST_BLOCKING 8 #define MAX_PACKET_LENGTH (256L*256L*256L-1) -static my_bool net_write_buff(NET *net,const char *packet,ulong len); +static my_bool net_write_buff(NET *net,const uchar *packet,ulong len); /* Init with packet info */ @@ -117,7 +117,7 @@ my_bool my_net_init(NET *net, Vio* vio) { DBUG_ENTER("my_net_init"); my_net_local_init(net); /* Set some limits */ - if (!(net->buff=(uchar*) my_malloc((uint32) net->max_packet+ + if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+ NET_HEADER_SIZE + COMP_HEADER_SIZE, MYF(MY_WME)))) DBUG_RETURN(1); @@ -157,7 +157,7 @@ my_bool my_net_init(NET *net, Vio* vio) void net_end(NET *net) { DBUG_ENTER("net_end"); - my_free((gptr) net->buff,MYF(MY_ALLOW_ZERO_PTR)); + my_free(net->buff,MYF(MY_ALLOW_ZERO_PTR)); net->buff=0; DBUG_VOID_RETURN; } @@ -165,17 +165,17 @@ void net_end(NET *net) /* Realloc the packet buffer */ -my_bool net_realloc(NET *net, ulong length) +my_bool net_realloc(NET *net, size_t length) { uchar *buff; - ulong pkt_length; + size_t pkt_length; DBUG_ENTER("net_realloc"); - DBUG_PRINT("enter",("length: %lu", length)); + DBUG_PRINT("enter",("length: %lu", (ulong) length)); if (length >= net->max_packet_size) { DBUG_PRINT("error", ("Packet too large. Max size: %lu", - net->max_packet_size)); + net->max_packet_size)); net->error= 1; net->report_error= 1; net->last_errno= ER_NET_PACKET_TOO_LARGE; @@ -186,9 +186,9 @@ my_bool net_realloc(NET *net, ulong length) We must allocate some extra bytes for the end 0 and to be able to read big compressed blocks */ - if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length + - NET_HEADER_SIZE + COMP_HEADER_SIZE, - MYF(MY_WME)))) + if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length + + NET_HEADER_SIZE + COMP_HEADER_SIZE, + MYF(MY_WME)))) { net->error= 1; net->report_error= 1; @@ -196,7 +196,7 @@ my_bool net_realloc(NET *net, ulong length) DBUG_RETURN(1); } net->buff=net->write_pos=buff; - net->buff_end=buff+(net->max_packet=pkt_length); + net->buff_end=buff+(net->max_packet= (ulong) pkt_length); DBUG_RETURN(0); } @@ -283,7 +283,8 @@ static int net_data_is_ready(my_socket sd) void net_clear(NET *net, my_bool clear_buffer) { #if !defined(EMBEDDED_LIBRARY) - int count, ready; + size_t count; + int ready; #endif DBUG_ENTER("net_clear"); @@ -293,14 +294,14 @@ void net_clear(NET *net, my_bool clear_buffer) while ((ready= net_data_is_ready(net->vio->sd)) > 0) { /* The socket is ready */ - if ((count= vio_read(net->vio, (char*) (net->buff), - (uint32) net->max_packet)) > 0) + if ((long) (count= vio_read(net->vio, net->buff, + (size_t) net->max_packet)) > 0) { - DBUG_PRINT("info",("skipped %d bytes from file: %s", - count, vio_description(net->vio))); + DBUG_PRINT("info",("skipped %ld bytes from file: %s", + (long) count, vio_description(net->vio))); #if defined(EXTRA_DEBUG) - fprintf(stderr,"Note: net_clear() skipped %d bytes from file: %s\n", - count, vio_description(net->vio)); + fprintf(stderr,"Note: net_clear() skipped %ld bytes from file: %s\n", + (long) count, vio_description(net->vio)); #endif } else @@ -318,10 +319,10 @@ void net_clear(NET *net, my_bool clear_buffer) my_bool old_mode; if (!vio_blocking(net->vio, FALSE, &old_mode)) { - while ((count= vio_read(net->vio, (char*) (net->buff), - (uint32) net->max_packet)) > 0) - DBUG_PRINT("info",("skipped %d bytes from file: %s", - count, vio_description(net->vio))); + while ((long) (count= vio_read(net->vio, net->buff, + (size_t) net->max_packet)) > 0) + DBUG_PRINT("info",("skipped %ld bytes from file: %s", + (long) count, vio_description(net->vio))); vio_blocking(net->vio, TRUE, &old_mode); } } @@ -342,8 +343,8 @@ my_bool net_flush(NET *net) DBUG_ENTER("net_flush"); if (net->buff != net->write_pos) { - error=test(net_real_write(net,(char*) net->buff, - (ulong) (net->write_pos - net->buff))); + error=test(net_real_write(net, net->buff, + (size_t) (net->write_pos - net->buff))); net->write_pos=net->buff; } /* Sync packet number if using compression */ @@ -367,7 +368,7 @@ my_bool net_flush(NET *net) */ my_bool -my_net_write(NET *net,const char *packet,ulong len) +my_net_write(NET *net,const uchar *packet,size_t len) { uchar buff[NET_HEADER_SIZE]; if (unlikely(!net->vio)) /* nowhere to write */ @@ -382,7 +383,7 @@ my_net_write(NET *net,const char *packet,ulong len) const ulong z_size = MAX_PACKET_LENGTH; int3store(buff, z_size); buff[3]= (uchar) net->pkt_nr++; - if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) || + if (net_write_buff(net, buff, NET_HEADER_SIZE) || net_write_buff(net, packet, z_size)) return 1; packet += z_size; @@ -391,10 +392,10 @@ my_net_write(NET *net,const char *packet,ulong len) /* Write last packet */ int3store(buff,len); buff[3]= (uchar) net->pkt_nr++; - if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) + if (net_write_buff(net, buff, NET_HEADER_SIZE)) return 1; #ifndef DEBUG_DATA_PACKETS - DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE); + DBUG_DUMP("packet_header", buff, NET_HEADER_SIZE); #endif return test(net_write_buff(net,packet,len)); } @@ -429,8 +430,8 @@ my_net_write(NET *net,const char *packet,ulong len) my_bool net_write_command(NET *net,uchar command, - const char *header, ulong head_len, - const char *packet, ulong len) + const uchar *header, size_t head_len, + const uchar *packet, size_t len) { ulong length=len+1+head_len; /* 1 extra byte for command */ uchar buff[NET_HEADER_SIZE+1]; @@ -448,7 +449,7 @@ net_write_command(NET *net,uchar command, { int3store(buff, MAX_PACKET_LENGTH); buff[3]= (uchar) net->pkt_nr++; - if (net_write_buff(net,(char*) buff, header_size) || + if (net_write_buff(net, buff, header_size) || net_write_buff(net, header, head_len) || net_write_buff(net, packet, len)) DBUG_RETURN(1); @@ -462,9 +463,9 @@ net_write_command(NET *net,uchar command, } int3store(buff,length); buff[3]= (uchar) net->pkt_nr++; - DBUG_RETURN(test(net_write_buff(net, (char*) buff, header_size) || - (head_len && net_write_buff(net, (char*) header, head_len)) || - net_write_buff(net, packet, len) || net_flush(net))); + DBUG_RETURN(test(net_write_buff(net, buff, header_size) || + (head_len && net_write_buff(net, header, head_len)) || + net_write_buff(net, packet, len) || net_flush(net))); } /* @@ -497,7 +498,7 @@ net_write_command(NET *net,uchar command, */ static my_bool -net_write_buff(NET *net,const char *packet,ulong len) +net_write_buff(NET *net, const uchar *packet, ulong len) { ulong left_length; if (net->compress && net->max_packet > MAX_PACKET_LENGTH) @@ -514,8 +515,8 @@ net_write_buff(NET *net,const char *packet,ulong len) { /* Fill up already used packet and write it */ memcpy((char*) net->write_pos,packet,left_length); - if (net_real_write(net,(char*) net->buff, - (ulong) (net->write_pos - net->buff) + left_length)) + if (net_real_write(net, net->buff, + (size_t) (net->write_pos - net->buff) + left_length)) return 1; net->write_pos= net->buff; packet+= left_length; @@ -552,10 +553,10 @@ net_write_buff(NET *net,const char *packet,ulong len) */ int -net_real_write(NET *net,const char *packet,ulong len) +net_real_write(NET *net,const uchar *packet, size_t len) { - long int length; - char *pos,*end; + size_t length; + const uchar *pos,*end; thr_alarm_t alarmed; #ifndef NO_ALARM ALARM alarm_buff; @@ -565,7 +566,7 @@ net_real_write(NET *net,const char *packet,ulong len) DBUG_ENTER("net_real_write"); #if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE) - query_cache_insert(net, packet, len); + query_cache_insert(net, (char*) packet, len); #endif if (net->error == 2) @@ -575,11 +576,11 @@ net_real_write(NET *net,const char *packet,ulong len) #ifdef HAVE_COMPRESS if (net->compress) { - ulong complen; + size_t complen; uchar *b; uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; - if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE + - COMP_HEADER_SIZE, MYF(MY_WME)))) + if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE + + COMP_HEADER_SIZE, MYF(MY_WME)))) { #ifdef MYSQL_SERVER net->last_errno= ER_OUT_OF_RESOURCES; @@ -592,39 +593,40 @@ net_real_write(NET *net,const char *packet,ulong len) } memcpy(b+header_length,packet,len); - if (my_compress((byte*) b+header_length,&len,&complen)) + if (my_compress(b+header_length, &len, &complen)) complen=0; int3store(&b[NET_HEADER_SIZE],complen); int3store(b,len); b[3]=(uchar) (net->compress_pkt_nr++); len+= header_length; - packet= (char*) b; + packet= b; } #endif /* HAVE_COMPRESS */ #ifdef DEBUG_DATA_PACKETS - DBUG_DUMP("data",packet,len); + DBUG_DUMP("data", packet, len); #endif #ifndef NO_ALARM thr_alarm_init(&alarmed); if (net_blocking) - thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff); + thr_alarm(&alarmed, net->write_timeout, &alarm_buff); #else alarmed=0; - /* Write timeout is set in net_set_write_timeout */ + /* Write timeout is set in my_net_set_write_timeout */ #endif /* NO_ALARM */ - pos=(char*) packet; end=pos+len; + pos= packet; + end=pos+len; while (pos != end) { - if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0) + if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0) { my_bool interrupted = vio_should_retry(net->vio); #if !defined(__WIN__) - if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed)) + if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed)) { - if (!thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff)) + if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff)) { /* Always true for client */ my_bool old_mode; while (vio_blocking(net->vio, TRUE, &old_mode) < 0) @@ -701,14 +703,14 @@ net_real_write(NET *net,const char *packet,ulong len) #ifndef NO_ALARM -static my_bool net_safe_read(NET *net, char *buff, uint32 length, +static my_bool net_safe_read(NET *net, uchar *buff, size_t length, thr_alarm_t *alarmed) { uint retry_count=0; while (length > 0) { - int tmp; - if ((tmp=vio_read(net->vio,(char*) net->buff, length)) <= 0) + size_t tmp; + if ((long) (tmp= vio_read(net->vio, buff, length)) <= 0) { my_bool interrupted = vio_should_retry(net->vio); if (!thr_got_alarm(alarmed) && interrupted) @@ -719,6 +721,7 @@ static my_bool net_safe_read(NET *net, char *buff, uint32 length, return 1; } length-= tmp; + buff+= tmp; } return 0; } @@ -759,15 +762,15 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, { while (remain > 0) { - uint length= min(remain, net->max_packet); - if (net_safe_read(net, (char*) net->buff, length, alarmed)) + size_t length= min(remain, net->max_packet); + if (net_safe_read(net, net->buff, length, alarmed)) DBUG_RETURN(1); update_statistics(thd_increment_bytes_received(length)); remain -= (uint32) length; } if (old != MAX_PACKET_LENGTH) break; - if (net_safe_read(net, (char*) net->buff, NET_HEADER_SIZE, alarmed)) + if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed)) DBUG_RETURN(1); old=remain= uint3korr(net->buff); net->pkt_nr++; @@ -784,10 +787,10 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, */ static ulong -my_real_read(NET *net, ulong *complen) +my_real_read(NET *net, size_t *complen) { uchar *pos; - long length; + size_t length; uint i,retry_count=0; ulong len=packet_error; thr_alarm_t alarmed; @@ -805,7 +808,7 @@ my_real_read(NET *net, ulong *complen) if (net_blocking) thr_alarm(&alarmed,net->read_timeout,&alarm_buff); #else - /* Read timeout is set in net_set_read_timeout */ + /* Read timeout is set in my_net_set_read_timeout */ #endif /* NO_ALARM */ pos = net->buff + net->where_b; /* net->packet -4 */ @@ -814,12 +817,12 @@ my_real_read(NET *net, ulong *complen) while (remain > 0) { /* First read is done with non blocking mode */ - if ((int) (length=vio_read(net->vio,(char*) pos,remain)) <= 0L) + if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L) { my_bool interrupted = vio_should_retry(net->vio); DBUG_PRINT("info",("vio_read returned %ld errno: %d", - length, vio_errno(net->vio))); + (long) length, vio_errno(net->vio))); #if !defined(__WIN__) || defined(MYSQL_SERVER) /* We got an error that there was no data on the socket. We now set up @@ -875,7 +878,7 @@ my_real_read(NET *net, ulong *complen) } #endif DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld", - remain, vio_errno(net->vio), length)); + remain, vio_errno(net->vio), (long) length)); len= packet_error; net->error= 2; /* Close socket */ net->report_error= 1; @@ -886,13 +889,13 @@ my_real_read(NET *net, ulong *complen) goto end; } remain -= (uint32) length; - pos+= (ulong) length; + pos+= length; update_statistics(thd_increment_bytes_received(length)); } if (i == 0) { /* First parts is packet length */ ulong helping; - DBUG_DUMP("packet_header",(char*) net->buff+net->where_b, + DBUG_DUMP("packet_header", net->buff+net->where_b, NET_HEADER_SIZE); if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) { @@ -963,7 +966,7 @@ end: net->reading_or_writing=0; #ifdef DEBUG_DATA_PACKETS if (len != packet_error) - DBUG_DUMP("data",(char*) net->buff+net->where_b, len); + DBUG_DUMP("data", net->buff+net->where_b, len); #endif return(len); } @@ -985,7 +988,7 @@ end: ulong my_net_read(NET *net) { - ulong len,complen; + size_t len, complen; #ifdef HAVE_COMPRESS if (!net->compress) @@ -996,7 +999,7 @@ my_net_read(NET *net) { /* First packet of a multi-packet. Concatenate the packets */ ulong save_pos = net->where_b; - ulong total_length=0; + size_t total_length= 0; do { net->where_b += len; @@ -1094,7 +1097,7 @@ my_net_read(NET *net) net->where_b=buf_length; if ((packet_len = my_real_read(net,&complen)) == packet_error) return packet_error; - if (my_uncompress((byte*) net->buff + net->where_b, &packet_len, + if (my_uncompress(net->buff + net->where_b, packet_len, &complen)) { net->error= 2; /* caller will close socket */ @@ -1104,7 +1107,7 @@ my_net_read(NET *net) #endif return packet_error; } - buf_length+=packet_len; + buf_length+= complen; } net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE; @@ -1120,25 +1123,27 @@ my_net_read(NET *net) } -void net_set_read_timeout(NET *net, uint timeout) +void my_net_set_read_timeout(NET *net, uint timeout) { - DBUG_ENTER("net_set_read_timeout"); + DBUG_ENTER("my_net_set_read_timeout"); DBUG_PRINT("enter", ("timeout: %d", timeout)); net->read_timeout= timeout; #ifdef NO_ALARM - vio_timeout(net->vio, 0, timeout); + if (net->vio) + vio_timeout(net->vio, 0, timeout); #endif DBUG_VOID_RETURN; } -void net_set_write_timeout(NET *net, uint timeout) +void my_net_set_write_timeout(NET *net, uint timeout) { - DBUG_ENTER("net_set_write_timeout"); + DBUG_ENTER("my_net_set_write_timeout"); DBUG_PRINT("enter", ("timeout: %d", timeout)); net->write_timeout= timeout; #ifdef NO_ALARM - vio_timeout(net->vio, 1, timeout); + if (net->vio) + vio_timeout(net->vio, 1, timeout); #endif DBUG_VOID_RETURN; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 96ae6174fdb..4944c994d3d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -80,9 +80,9 @@ */ #define double2rows(x) ((ha_rows)(x)) -static int sel_cmp(Field *f,char *a,char *b,uint8 a_flag,uint8 b_flag); +static int sel_cmp(Field *f,uchar *a,uchar *b,uint8 a_flag,uint8 b_flag); -static char is_null_string[2]= {1,0}; +static uchar is_null_string[2]= {1,0}; class RANGE_OPT_PARAM; /* @@ -274,7 +274,7 @@ public: ulong use_count; Field *field; - char *min_value,*max_value; // Pointer to range + uchar *min_value,*max_value; // Pointer to range SEL_ARG *left,*right; /* R-B tree children */ SEL_ARG *next,*prev; /* Links for bi-directional interval list */ @@ -287,8 +287,8 @@ public: SEL_ARG() {} SEL_ARG(SEL_ARG &); - SEL_ARG(Field *,const char *,const char *); - SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value, + SEL_ARG(Field *,const uchar *, const uchar *); + SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); SEL_ARG(enum Type type_arg) :min_flag(0),elements(1),use_count(1),left(0),next_key_part(0), @@ -324,7 +324,7 @@ public: } SEL_ARG *clone_and(SEL_ARG* arg) { // Get overlapping range - char *new_min,*new_max; + uchar *new_min,*new_max; uint8 flag_min,flag_max; if (cmp_min_to_min(arg) >= 0) { @@ -398,7 +398,7 @@ public: min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN; } /* returns a number of keypart values (0 or 1) appended to the key buffer */ - int store_min(uint length,char **min_key,uint min_key_flag) + int store_min(uint length, uchar **min_key,uint min_key_flag) { if ((min_flag & GEOM_FLAG) || (!(min_flag & NO_MIN_RANGE) && @@ -417,7 +417,7 @@ public: return 0; } /* returns a number of keypart values (0 or 1) appended to the key buffer */ - int store_max(uint length,char **max_key, uint max_key_flag) + int store_max(uint length, uchar **max_key, uint max_key_flag) { if (!(max_flag & NO_MAX_RANGE) && !(max_key_flag & (NO_MAX_RANGE | NEAR_MAX))) @@ -436,7 +436,7 @@ public: } /* returns a number of keypart values appended to the key buffer */ - int store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag) + int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag) { SEL_ARG *key_tree= first(); uint res= key_tree->store_min(key[key_tree->part].store_length, @@ -452,7 +452,7 @@ public: } /* returns a number of keypart values appended to the key buffer */ - int store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag) + int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag) { SEL_ARG *key_tree= last(); uint res=key_tree->store_max(key[key_tree->part].store_length, @@ -534,8 +534,8 @@ public: */ if (min_flag || max_flag) return FALSE; - byte *min_val= (byte *)min_value; - byte *max_val= (byte *)max_value; + uchar *min_val= min_value; + uchar *max_val= max_value; if (maybe_null) { @@ -641,8 +641,7 @@ public: longlong baseflag; uint max_key_part, range_count; - - char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH], + uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH], max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; bool quick; // Don't calulate possible keys @@ -683,8 +682,8 @@ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts); static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree, bool update_tbl_stats); static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree, - char *min_key, uint min_key_flag, int, - char *max_key, uint max_key_flag, int); + uchar *min_key, uint min_key_flag, int, + uchar *max_key, uint max_key_flag, int); QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index, SEL_ARG *key_tree, @@ -726,12 +725,12 @@ static SEL_ARG *key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag); static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1); bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, - SEL_ARG *key_tree,char *min_key,uint min_key_flag, - char *max_key,uint max_key_flag); + SEL_ARG *key_tree, uchar *min_key,uint min_key_flag, + uchar *max_key,uint max_key_flag); static bool eq_tree(SEL_ARG* a,SEL_ARG *b); static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE); -static bool null_part_in_key(KEY_PART *key_part, const char *key, +static bool null_part_in_key(KEY_PART *key_part, const uchar *key, uint length); bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, RANGE_OPT_PARAM* param); @@ -986,7 +985,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, select->file= *head->sort.io_cache; select->records=(ha_rows) (select->file.end_of_file/ head->file->ref_length); - my_free((gptr) (head->sort.io_cache),MYF(0)); + my_free(head->sort.io_cache, MYF(0)); head->sort.io_cache=0; } DBUG_RETURN(select); @@ -1192,8 +1191,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param, init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); else bzero(&alloc, sizeof(MEM_ROOT)); - last_rowid= (byte*)alloc_root(parent_alloc? parent_alloc : &alloc, - head->file->ref_length); + last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc, + head->file->ref_length); } @@ -1450,7 +1449,7 @@ int QUICK_ROR_UNION_SELECT::init() DBUG_RETURN(1); } - if (!(cur_rowid= (byte*)alloc_root(&alloc, 2*head->file->ref_length))) + if (!(cur_rowid= (uchar*) alloc_root(&alloc, 2*head->file->ref_length))) DBUG_RETURN(1); prev_rowid= cur_rowid + head->file->ref_length; DBUG_RETURN(0); @@ -1468,7 +1467,7 @@ int QUICK_ROR_UNION_SELECT::init() val2 Second merged select */ -int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, byte *val1, byte *val2) +int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, uchar *val1, uchar *val2) { QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg; return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid, @@ -1519,7 +1518,7 @@ int QUICK_ROR_UNION_SELECT::reset() DBUG_RETURN(error); } quick->save_last_pos(); - queue_insert(&queue, (byte*)quick); + queue_insert(&queue, (uchar*)quick); } if (head->file->ha_rnd_init(1)) @@ -1580,16 +1579,18 @@ inline void SEL_ARG::make_root() use_count=0; elements=1; } -SEL_ARG::SEL_ARG(Field *f,const char *min_value_arg,const char *max_value_arg) +SEL_ARG::SEL_ARG(Field *f,const uchar *min_value_arg, + const uchar *max_value_arg) :min_flag(0), max_flag(0), maybe_flag(0), maybe_null(f->real_maybe_null()), - elements(1), use_count(1), field(f), min_value((char*) min_value_arg), - max_value((char*) max_value_arg), next(0),prev(0), + elements(1), use_count(1), field(f), min_value((uchar*) min_value_arg), + max_value((uchar*) max_value_arg), next(0),prev(0), next_key_part(0),color(BLACK),type(KEY_RANGE) { left=right= &null_element; } -SEL_ARG::SEL_ARG(Field *field_,uint8 part_,char *min_value_,char *max_value_, +SEL_ARG::SEL_ARG(Field *field_,uint8 part_, + uchar *min_value_, uchar *max_value_, uint8 min_flag_,uint8 max_flag_,uint8 maybe_flag_) :min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_), part(part_),maybe_null(field_->real_maybe_null()), elements(1),use_count(1), @@ -1667,7 +1668,8 @@ SEL_ARG *SEL_ARG::last() Returns -2 or 2 if the ranges where 'joined' like < 2 and >= 2 */ -static int sel_cmp(Field *field, char *a,char *b,uint8 a_flag,uint8 b_flag) +static int sel_cmp(Field *field, uchar *a, uchar *b, uint8 a_flag, + uint8 b_flag) { int cmp; /* First check if there was a compare to a min or max element */ @@ -1691,7 +1693,7 @@ static int sel_cmp(Field *field, char *a,char *b,uint8 a_flag,uint8 b_flag) goto end; // NULL where equal a++; b++; // Skip NULL marker } - cmp=field->key_cmp((byte*) a,(byte*) b); + cmp=field->key_cmp(a , b); if (cmp) return cmp < 0 ? -1 : 1; // The values differed // Check if the compared equal arguments was defined with open/closed range @@ -1970,7 +1972,7 @@ private: KEY *index_info; uint index; uint key_infix_len; - byte key_infix[MAX_KEY_LENGTH]; + uchar key_infix[MAX_KEY_LENGTH]; SEL_TREE *range_tree; /* Represents all range predicates in the query. */ SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */ uint param_idx; /* Index of used key in param->key. */ @@ -1983,7 +1985,7 @@ public: uint group_prefix_len_arg, uint used_key_parts_arg, uint group_key_parts_arg, KEY *index_info_arg, uint index_arg, uint key_infix_len_arg, - byte *key_infix_arg, + uchar *key_infix_arg, SEL_TREE *tree_arg, SEL_ARG *index_tree_arg, uint param_idx_arg, ha_rows quick_prefix_records_arg) : have_min(have_min_arg), have_max(have_max_arg), @@ -2714,7 +2716,7 @@ end: format. */ -void store_key_image_to_rec(Field *field, char *ptr, uint len) +void store_key_image_to_rec(Field *field, uchar *ptr, uint len) { /* Do the same as print_key() does */ my_bitmap_map *old_map; @@ -3416,7 +3418,7 @@ static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part) DBUG_LOCK_FILE; if (!(arg->min_flag & NO_MIN_RANGE)) { - store_key_image_to_rec(part->field, (char*)(arg->min_value), part->length); + store_key_image_to_rec(part->field, arg->min_value, part->length); dbug_print_field(part->field); if (arg->min_flag & NEAR_MIN) fputs(" < ", DBUG_FILE); @@ -3432,7 +3434,7 @@ static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part) fputs(" < ", DBUG_FILE); else fputs(" <= ", DBUG_FILE); - store_key_image_to_rec(part->field, (char*)(arg->max_value), part->length); + store_key_image_to_rec(part->field, arg->max_value, part->length); dbug_print_field(part->field); } fputs("\n", DBUG_FILE); @@ -4169,8 +4171,8 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, { double selectivity_mult= 1.0; KEY_PART_INFO *key_part= info->param->table->key_info[scan->keynr].key_part; - byte key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */ - char *key_ptr= (char*) key_val; + uchar key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */ + uchar *key_ptr= key_val; SEL_ARG *sel_arg, *tuple_arg= NULL; key_part_map keypart_map= 0; bool cur_covered; @@ -4178,9 +4180,9 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, key_part->fieldnr-1)); key_range min_range; key_range max_range; - min_range.key= (byte*) key_val; + min_range.key= key_val; min_range.flag= HA_READ_KEY_EXACT; - max_range.key= (byte*) key_val; + max_range.key= key_val; max_range.flag= HA_READ_AFTER_KEY; ha_rows prev_records= info->param->table->file->stats.records; DBUG_ENTER("ror_scan_selectivity"); @@ -4209,7 +4211,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, &key_ptr, 0); keypart_map= (keypart_map << 1) | 1; } - min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val); + min_range.length= max_range.length= (size_t) (key_ptr - key_val); min_range.keypart_map= max_range.keypart_map= keypart_map; records= (info->param->table->file-> records_in_range(scan->keynr, &min_range, &max_range)); @@ -5549,7 +5551,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, bool optimize_range; SEL_ARG *tree= 0; MEM_ROOT *alloc= param->mem_root; - char *str; + uchar *str; ulong orig_sql_mode; int err; DBUG_ENTER("get_mm_leaf"); @@ -5611,9 +5613,10 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, if (type == Item_func::LIKE_FUNC) { bool like_error; - char buff1[MAX_FIELD_WIDTH],*min_str,*max_str; + char buff1[MAX_FIELD_WIDTH]; + uchar *min_str,*max_str; String tmp(buff1,sizeof(buff1),value->collation.collation),*res; - uint length,offset,min_length,max_length; + size_t length, offset, min_length, max_length; uint field_length= field->pack_length()+maybe_null; if (!optimize_range) @@ -5660,7 +5663,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, field_length= length; } length+=offset; - if (!(min_str= (char*) alloc_root(alloc, length*2))) + if (!(min_str= (uchar*) alloc_root(alloc, length*2))) goto end; max_str=min_str+length; @@ -5673,7 +5676,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, ((Item_func_like*)(param->cond))->escape, wild_one, wild_many, field_length, - min_str+offset, max_str+offset, + (char*) min_str+offset, (char*) max_str+offset, &min_length, &max_length); if (like_error) // Can't optimize with LIKE goto end; @@ -5735,12 +5738,13 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, goto end; } field->table->in_use->variables.sql_mode= orig_sql_mode; - str= (char*) alloc_root(alloc, key_part->store_length+1); + str= (uchar*) alloc_root(alloc, key_part->store_length+1); if (!str) goto end; if (maybe_null) - *str= (char) field->is_real_null(); // Set to 1 if null - field->get_key_image(str+maybe_null, key_part->length, key_part->image_type); + *str= (uchar) field->is_real_null(); // Set to 1 if null + field->get_key_image(str+maybe_null, key_part->length, + key_part->image_type); if (!(tree= new (alloc) SEL_ARG(field, str, str))) goto end; // out of memory @@ -7244,13 +7248,13 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats) static ha_rows check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree, - char *min_key, uint min_key_flag, int min_keypart, - char *max_key, uint max_key_flag, int max_keypart) + uchar *min_key, uint min_key_flag, int min_keypart, + uchar *max_key, uint max_key_flag, int max_keypart) { ha_rows records=0, tmp; uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length; uint tmp_min_keypart= min_keypart, tmp_max_keypart= max_keypart; - char *tmp_min_key, *tmp_max_key; + uchar *tmp_min_key, *tmp_max_key; uint8 save_first_null_comp= param->first_null_comp; param->max_key_part=max(param->max_key_part,key_tree->part); @@ -7370,7 +7374,7 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree, if (tmp_min_flag & GEOM_FLAG) { key_range min_range; - min_range.key= (byte*) param->min_key; + min_range.key= param->min_key; min_range.length= min_key_length; min_range.keypart_map= make_keypart_map(tmp_min_keypart); /* In this case tmp_min_flag contains the handler-read-function */ @@ -7383,12 +7387,12 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree, { key_range min_range, max_range; - min_range.key= (byte*) param->min_key; + min_range.key= param->min_key; min_range.length= min_key_length; min_range.flag= (tmp_min_flag & NEAR_MIN ? HA_READ_AFTER_KEY : HA_READ_KEY_EXACT); min_range.keypart_map= make_keypart_map(tmp_min_keypart); - max_range.key= (byte*) param->max_key; + max_range.key= param->max_key; max_range.length= max_key_length; max_range.flag= (tmp_max_flag & NEAR_MAX ? HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY); @@ -7557,8 +7561,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree, */ bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, - SEL_ARG *key_tree,char *min_key,uint min_key_flag, - char *max_key, uint max_key_flag) + SEL_ARG *key_tree, uchar *min_key,uint min_key_flag, + uchar *max_key, uint max_key_flag) { QUICK_RANGE *range; uint flag; @@ -7571,7 +7575,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, min_key,min_key_flag, max_key, max_key_flag)) return 1; } - char *tmp_min_key=min_key,*tmp_max_key=max_key; + uchar *tmp_min_key=min_key,*tmp_max_key=max_key; min_part+= key_tree->store_min(key[key_tree->part].store_length, &tmp_min_key,min_key_flag); max_part+= key_tree->store_max(key[key_tree->part].store_length, @@ -7595,10 +7599,10 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag; if (!tmp_min_flag) min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key, - &tmp_min_flag); + &tmp_min_flag); if (!tmp_max_flag) max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key, - &tmp_max_flag); + &tmp_max_flag); flag=tmp_min_flag | tmp_max_flag; } } @@ -7646,10 +7650,10 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, } /* Get range for retrieving rows in QUICK_SELECT::get_next */ - if (!(range= new QUICK_RANGE((const char *) param->min_key, + if (!(range= new QUICK_RANGE(param->min_key, (uint) (tmp_min_key - param->min_key), min_part >=0 ? make_keypart_map(min_part) : 0, - (const char *) param->max_key, + param->max_key, (uint) (tmp_max_key - param->max_key), max_part >=0 ? make_keypart_map(max_part) : 0, flag))) @@ -7658,7 +7662,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, set_if_bigger(quick->max_used_key_length, range->min_length); set_if_bigger(quick->max_used_key_length, range->max_length); set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1); - if (insert_dynamic(&quick->ranges, (gptr)&range)) + if (insert_dynamic(&quick->ranges, (uchar*) &range)) return 1; end: @@ -7691,9 +7695,9 @@ bool QUICK_RANGE_SELECT::unique_key_range() /* Returns TRUE if any part of the key is NULL */ -static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) +static bool null_part_in_key(KEY_PART *key_part, const uchar *key, uint length) { - for (const char *end=key+length ; + for (const uchar *end=key+length ; key < end; key+= key_part++->store_length) { @@ -7796,7 +7800,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, !(range= new(alloc) QUICK_RANGE())) goto err; // out of memory - range->min_key= range->max_key= (char*) ref->key_buff; + range->min_key= range->max_key= ref->key_buff; range->min_length= range->max_length= ref->key_length; range->min_keypart_map= range->max_keypart_map= make_prev_keypart_map(ref->key_parts); @@ -7817,7 +7821,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, key_part->null_bit= key_info->key_part[part].null_bit; key_part->flag= (uint8) key_info->key_part[part].key_part_flag; } - if (insert_dynamic(&quick->ranges,(gptr)&range)) + if (insert_dynamic(&quick->ranges,(uchar*)&range)) goto err; /* @@ -7832,13 +7836,13 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, *ref->null_ref_key= 1; // Set null byte then create a range if (!(null_range= new (alloc) - QUICK_RANGE((char*)ref->key_buff, ref->key_length, + QUICK_RANGE(ref->key_buff, ref->key_length, make_prev_keypart_map(ref->key_parts), - (char*)ref->key_buff, ref->key_length, + ref->key_buff, ref->key_length, make_prev_keypart_map(ref->key_parts), EQ_RANGE))) goto err; *ref->null_ref_key= 0; // Clear null byte - if (insert_dynamic(&quick->ranges,(gptr)&null_range)) + if (insert_dynamic(&quick->ranges,(uchar*)&null_range)) goto err; } @@ -8093,7 +8097,7 @@ int QUICK_ROR_UNION_SELECT::get_next() { int error, dup_row; QUICK_SELECT_I *quick; - byte *tmp; + uchar *tmp; DBUG_ENTER("QUICK_ROR_UNION_SELECT::get_next"); do @@ -8143,7 +8147,7 @@ int QUICK_ROR_UNION_SELECT::get_next() int QUICK_RANGE_SELECT::reset() { uint mrange_bufsiz; - byte *mrange_buff; + uchar *mrange_buff; DBUG_ENTER("QUICK_RANGE_SELECT::reset"); next=0; last_range= NULL; @@ -8186,8 +8190,9 @@ int QUICK_RANGE_SELECT::reset() while (mrange_bufsiz && ! my_multi_malloc(MYF(MY_WME), - &multi_range_buff, sizeof(*multi_range_buff), - &mrange_buff, mrange_bufsiz, + &multi_range_buff, + (uint) sizeof(*multi_range_buff), + &mrange_buff, (uint) mrange_bufsiz, NullS)) { /* Try to shrink the buffers until both are 0. */ @@ -8282,13 +8287,13 @@ int QUICK_RANGE_SELECT::get_next() end_key= &mrange_slot->end_key; last_range= *(cur_range++); - start_key->key= (const byte*) last_range->min_key; + start_key->key= (const uchar*) last_range->min_key; start_key->length= last_range->min_length; start_key->flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : (last_range->flag & EQ_RANGE) ? HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); start_key->keypart_map= last_range->min_keypart_map; - end_key->key= (const byte*) last_range->max_key; + end_key->key= (const uchar*) last_range->max_key; end_key->length= last_range->max_length; /* We use HA_READ_AFTER_KEY here because if we are reading on a key @@ -8348,7 +8353,7 @@ end: int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, key_part_map keypart_map, - byte *cur_prefix) + uchar *cur_prefix) { DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix"); @@ -8374,13 +8379,13 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, } last_range= *(cur_range++); - start_key.key= (const byte*) last_range->min_key; + start_key.key= (const uchar*) last_range->min_key; start_key.length= min(last_range->min_length, prefix_length); start_key.keypart_map= last_range->min_keypart_map & keypart_map; start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : (last_range->flag & EQ_RANGE) ? HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); - end_key.key= (const byte*) last_range->max_key; + end_key.key= (const uchar*) last_range->max_key; end_key.length= min(last_range->max_length, prefix_length); end_key.keypart_map= last_range->max_keypart_map & keypart_map; /* @@ -8416,7 +8421,7 @@ int QUICK_RANGE_SELECT_GEOM::get_next() if (last_range) { // Already read through key - result= file->index_next_same(record, (byte*) last_range->min_key, + result= file->index_next_same(record, last_range->min_key, last_range->min_length); if (result != HA_ERR_END_OF_FILE) DBUG_RETURN(result); @@ -8431,7 +8436,7 @@ int QUICK_RANGE_SELECT_GEOM::get_next() } last_range= *(cur_range++); - result= file->index_read(record, (byte*) last_range->min_key, + result= file->index_read(record, last_range->min_key, last_range->min_keypart_map, (ha_rkey_function)(last_range->flag ^ GEOM_FLAG)); if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE) @@ -8536,7 +8541,7 @@ int QUICK_SELECT_DESC::get_next() if (last_range) { // Already read through key result = ((last_range->flag & EQ_RANGE) - ? file->index_next_same(record, (byte*) last_range->min_key, + ? file->index_next_same(record, last_range->min_key, last_range->min_length) : file->index_prev(record)); if (!result) @@ -8564,14 +8569,14 @@ int QUICK_SELECT_DESC::get_next() if (last_range->flag & EQ_RANGE) { - result = file->index_read(record, (byte*) last_range->max_key, + result = file->index_read(record, last_range->max_key, last_range->max_keypart_map, HA_READ_KEY_EXACT); } else { DBUG_ASSERT(last_range->flag & NEAR_MAX || range_reads_after_key(last_range)); - result=file->index_read(record, (byte*) last_range->max_key, + result=file->index_read(record, last_range->max_key, last_range->max_keypart_map, ((last_range->flag & NEAR_MAX) ? HA_READ_BEFORE_KEY : @@ -8608,7 +8613,7 @@ int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg) KEY_PART *key_part=key_parts; uint store_length; - for (char *key=range_arg->max_key, *end=key+range_arg->max_length; + for (uchar *key=range_arg->max_key, *end=key+range_arg->max_length; key < end; key+= store_length, key_part++) { @@ -8627,7 +8632,7 @@ int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg) key++; // Skip null byte store_length--; } - if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0) + if ((cmp=key_part->field->key_cmp(key, key_part->length)) < 0) return 0; if (cmp > 0) return 1; @@ -8646,7 +8651,7 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg) if (range_arg->flag & NO_MIN_RANGE) return 0; /* key can't be to small */ - cmp= key_cmp(key_part_info, (byte*) range_arg->min_key, + cmp= key_cmp(key_part_info, range_arg->min_key, range_arg->min_length); if (cmp > 0 || cmp == 0 && !(range_arg->flag & NEAR_MIN)) return 0; @@ -8896,7 +8901,7 @@ static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, KEY_PART_INFO *first_non_group_part, KEY_PART_INFO *min_max_arg_part, KEY_PART_INFO *last_part, THD *thd, - byte *key_infix, uint *key_infix_len, + uchar *key_infix, uint *key_infix_len, KEY_PART_INFO **first_non_infix_part); static bool check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item, @@ -9053,7 +9058,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) uint index= 0; /* The id of the chosen index. */ uint group_key_parts= 0; // Number of index key parts in the group prefix. uint used_key_parts= 0; /* Number of index key parts used for access. */ - byte key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/ + uchar key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/ uint key_infix_len= 0; /* Length of key_infix. */ TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */ uint key_part_nr; @@ -9337,7 +9342,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) /* Check if cur_part is referenced in the WHERE clause. */ if (join->conds->walk(&Item::find_item_in_field_list_processor, 0, - (byte*) key_part_range)) + (uchar*) key_part_range)) goto next_index; } } @@ -9607,7 +9612,7 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, KEY_PART_INFO *first_non_group_part, KEY_PART_INFO *min_max_arg_part, KEY_PART_INFO *last_part, THD *thd, - byte *key_infix, uint *key_infix_len, + uchar *key_infix, uint *key_infix_len, KEY_PART_INFO **first_non_infix_part) { SEL_ARG *cur_range; @@ -9616,7 +9621,7 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, KEY_PART_INFO *end_part= min_max_arg_part ? min_max_arg_part : last_part; *key_infix_len= 0; - byte *key_ptr= key_infix; + uchar *key_ptr= key_infix; for (cur_part= first_non_group_part; cur_part != end_part; cur_part++) { /* @@ -10006,7 +10011,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, uint used_key_parts_arg, KEY *index_info_arg, uint use_index, double read_cost_arg, ha_rows records_arg, uint key_infix_len_arg, - byte *key_infix_arg, MEM_ROOT *parent_alloc) + uchar *key_infix_arg, MEM_ROOT *parent_alloc) :join(join_arg), index_info(index_info_arg), group_prefix_len(group_prefix_len_arg), group_key_parts(group_key_parts_arg), have_min(have_min_arg), @@ -10065,13 +10070,13 @@ int QUICK_GROUP_MIN_MAX_SELECT::init() if (group_prefix) /* Already initialized. */ return 0; - if (!(last_prefix= (byte*) alloc_root(&alloc, group_prefix_len))) + if (!(last_prefix= (uchar*) alloc_root(&alloc, group_prefix_len))) return 1; /* We may use group_prefix to store keys with all select fields, so allocate enough space for it. */ - if (!(group_prefix= (byte*) alloc_root(&alloc, + if (!(group_prefix= (uchar*) alloc_root(&alloc, real_prefix_len + min_max_arg_len))) return 1; @@ -10081,7 +10086,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::init() The memory location pointed to by key_infix will be deleted soon, so allocate a new buffer and copy the key_infix into it. */ - byte *tmp_key_infix= (byte*) alloc_root(&alloc, key_infix_len); + uchar *tmp_key_infix= (uchar*) alloc_root(&alloc, key_infix_len); if (!tmp_key_infix) return 1; memcpy(tmp_key_infix, this->key_infix, key_infix_len); @@ -10196,7 +10201,7 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range) range_flag); if (!range) return TRUE; - if (insert_dynamic(&min_max_ranges, (gptr)&range)) + if (insert_dynamic(&min_max_ranges, (uchar*)&range)) return TRUE; return FALSE; } @@ -10231,7 +10236,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges () { QUICK_RANGE *range; - get_dynamic(arr, (gptr)&range, inx); + get_dynamic(arr, (uchar*)&range, inx); range->flag &= ~(NEAR_MIN | NEAR_MAX); } } @@ -10267,7 +10272,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() QUICK_RANGE *cur_range; if (have_min) { /* Check if the right-most range has a lower boundary. */ - get_dynamic(&min_max_ranges, (gptr)&cur_range, + get_dynamic(&min_max_ranges, (uchar*)&cur_range, min_max_ranges.elements - 1); if (!(cur_range->flag & NO_MIN_RANGE)) { @@ -10278,7 +10283,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() } if (have_max) { /* Check if the left-most range has an upper boundary. */ - get_dynamic(&min_max_ranges, (gptr)&cur_range, 0); + get_dynamic(&min_max_ranges, (uchar*)&cur_range, 0); if (!(cur_range->flag & NO_MAX_RANGE)) { max_used_key_length+= min_max_arg_len; @@ -10604,7 +10609,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix() if (quick_prefix_select) { - byte *cur_prefix= seen_first_key ? group_prefix : NULL; + uchar *cur_prefix= seen_first_key ? group_prefix : NULL; if ((result= quick_prefix_select->get_next_prefix(group_prefix_len, make_prev_keypart_map(group_key_parts), cur_prefix))) DBUG_RETURN(result); @@ -10674,14 +10679,14 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() for (uint range_idx= 0; range_idx < min_max_ranges.elements; range_idx++) { /* Search from the left-most range to the right. */ - get_dynamic(&min_max_ranges, (gptr)&cur_range, range_idx); + get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx); /* If the current value for the min/max argument is bigger than the right boundary of cur_range, there is no need to check this range. */ if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) && - (key_cmp(min_max_arg_part, (const byte*) cur_range->max_key, + (key_cmp(min_max_arg_part, (const uchar*) cur_range->max_key, min_max_arg_len) == 1)) continue; @@ -10742,7 +10747,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() if ( !(cur_range->flag & NO_MAX_RANGE) ) { /* Compose the MAX key for the range. */ - byte *max_key= (byte*) my_alloca(real_prefix_len + min_max_arg_len); + uchar *max_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len); memcpy(max_key, group_prefix, real_prefix_len); memcpy(max_key + real_prefix_len, cur_range->max_key, cur_range->max_length); @@ -10806,7 +10811,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() for (uint range_idx= min_max_ranges.elements; range_idx > 0; range_idx--) { /* Search from the right-most range to the left. */ - get_dynamic(&min_max_ranges, (gptr)&cur_range, range_idx - 1); + get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx - 1); /* If the current value for the min/max argument is smaller than the left @@ -10814,7 +10819,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() */ if (range_idx != min_max_ranges.elements && !(cur_range->flag & NO_MIN_RANGE) && - (key_cmp(min_max_arg_part, (const byte*) cur_range->min_key, + (key_cmp(min_max_arg_part, (const uchar*) cur_range->min_key, min_max_arg_len) == -1)) continue; @@ -10860,7 +10865,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() if ( !(cur_range->flag & NO_MIN_RANGE) ) { /* Compose the MIN key for the range. */ - byte *min_key= (byte*) my_alloca(real_prefix_len + min_max_arg_len); + uchar *min_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len); memcpy(min_key, group_prefix, real_prefix_len); memcpy(min_key + real_prefix_len, cur_range->min_key, cur_range->min_length); @@ -11031,10 +11036,10 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, *****************************************************************************/ static void -print_key(KEY_PART *key_part,const char *key,uint used_length) +print_key(KEY_PART *key_part, const uchar *key, uint used_length) { char buff[1024]; - const char *key_end= key+used_length; + const uchar *key_end= key+used_length; String tmp(buff,sizeof(buff),&my_charset_bin); uint store_length; TABLE *table= key_part->field->table; @@ -11057,7 +11062,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length) key++; // Skip null byte store_length--; } - field->set_key_image((char*) key, key_part->length); + field->set_key_image(key, key_part->length); if (field->type() == MYSQL_TYPE_BIT) (void) field->val_int_as_str(&tmp, 1); else @@ -11112,7 +11117,7 @@ void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose) range= *pr; if (!(range->flag & NO_MIN_RANGE)) { - print_key(key_parts,range->min_key,range->min_length); + print_key(key_parts, range->min_key, range->min_length); if (range->flag & NEAR_MIN) fputs(" < ",DBUG_FILE); else @@ -11126,7 +11131,7 @@ void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose) fputs(" < ",DBUG_FILE); else fputs(" <= ",DBUG_FILE); - print_key(key_parts,range->max_key,range->max_length); + print_key(key_parts, range->max_key, range->max_length); } fputs("\n",DBUG_FILE); } diff --git a/sql/opt_range.h b/sql/opt_range.h index 76a4caa1ccb..dd219129167 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -35,7 +35,7 @@ typedef struct st_key_part { class QUICK_RANGE :public Sql_alloc { public: - char *min_key,*max_key; + uchar *min_key,*max_key; uint16 min_length,max_length,flag; key_part_map min_keypart_map, // bitmap of used keyparts in min_key max_keypart_map; // bitmap of used keyparts in max_key @@ -43,13 +43,13 @@ class QUICK_RANGE :public Sql_alloc { uint16 dummy; /* Avoid warnings on 'flag' */ #endif QUICK_RANGE(); /* Full range */ - QUICK_RANGE(const char *min_key_arg, uint min_length_arg, + QUICK_RANGE(const uchar *min_key_arg, uint min_length_arg, key_part_map min_keypart_map_arg, - const char *max_key_arg, uint max_length_arg, + const uchar *max_key_arg, uint max_length_arg, key_part_map max_keypart_map_arg, uint flag_arg) - : min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)), - max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)), + : min_key((uchar*) sql_memdup(min_key_arg,min_length_arg+1)), + max_key((uchar*) sql_memdup(max_key_arg,max_length_arg+1)), min_length((uint16) min_length_arg), max_length((uint16) max_length_arg), flag((uint16) flag_arg), @@ -241,12 +241,12 @@ public: rowid of last row retrieved by this quick select. This is used only when doing ROR-index_merge selects */ - byte *last_rowid; + uchar *last_rowid; /* Table record buffer used by this quick select. */ - byte *record; + uchar *record; #ifndef DBUG_OFF /* Print quick select information to DBUG_FILE. Caller is responsible @@ -296,8 +296,8 @@ protected: friend bool get_quick_keys(PARAM *param, QUICK_RANGE_SELECT *quick,KEY_PART *key, SEL_ARG *key_tree, - char *min_key, uint min_key_flag, - char *max_key, uint max_key_flag); + uchar *min_key, uint min_key_flag, + uchar *max_key, uint max_key_flag); friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx, SEL_ARG *key_tree, MEM_ROOT *alloc); @@ -327,7 +327,7 @@ public: int get_next(); void range_end(); int get_next_prefix(uint prefix_length, key_part_map keypart_map, - byte *cur_prefix); + uchar *cur_prefix); bool reverse_sorted() { return 0; } bool unique_key_range(); int init_ror_merged_scan(bool reuse_handler); @@ -561,12 +561,12 @@ public: MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */ THD *thd; /* current thread */ - byte *cur_rowid; /* buffer used in get_next() */ - byte *prev_rowid; /* rowid of last row returned by get_next() */ + uchar *cur_rowid; /* buffer used in get_next() */ + uchar *prev_rowid; /* rowid of last row returned by get_next() */ bool have_prev_rowid; /* true if prev_rowid has valid data */ uint rowid_length; /* table rowid length */ private: - static int queue_cmp(void *arg, byte *val1, byte *val2); + static int queue_cmp(void *arg, uchar *val1, uchar *val2); bool scans_inited; }; @@ -610,19 +610,19 @@ private: handler *file; /* The handler used to get data. */ JOIN *join; /* Descriptor of the current query */ KEY *index_info; /* The index chosen for data access */ - byte *record; /* Buffer where the next record is returned. */ - byte *tmp_record; /* Temporary storage for next_min(), next_max(). */ - byte *group_prefix; /* Key prefix consisting of the GROUP fields. */ + uchar *record; /* Buffer where the next record is returned. */ + uchar *tmp_record; /* Temporary storage for next_min(), next_max(). */ + uchar *group_prefix; /* Key prefix consisting of the GROUP fields. */ uint group_prefix_len; /* Length of the group prefix. */ uint group_key_parts; /* A number of keyparts in the group prefix */ - byte *last_prefix; /* Prefix of the last group for detecting EOF. */ + uchar *last_prefix; /* Prefix of the last group for detecting EOF. */ bool have_min; /* Specify whether we are computing */ bool have_max; /* a MIN, a MAX, or both. */ bool seen_first_key; /* Denotes whether the first key was retrieved.*/ KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */ /* of all MIN/MAX functions. */ uint min_max_arg_len; /* The length of the MIN/MAX argument field */ - byte *key_infix; /* Infix of constants from equality predicates. */ + uchar *key_infix; /* Infix of constants from equality predicates. */ uint key_infix_len; DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */ uint real_prefix_len; /* Length of key prefix extended with key_infix. */ @@ -652,7 +652,7 @@ public: uint group_prefix_len, uint group_key_parts, uint used_key_parts, KEY *index_info, uint use_index, double read_cost, ha_rows records, uint - key_infix_len, byte *key_infix, MEM_ROOT + key_infix_len, uchar *key_infix, MEM_ROOT *parent_alloc); ~QUICK_GROUP_MIN_MAX_SELECT(); bool add_range(SEL_ARG *sel_range); @@ -736,7 +736,7 @@ uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit); #ifdef WITH_PARTITION_STORAGE_ENGINE bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond); -void store_key_image_to_rec(Field *field, char *ptr, uint len); +void store_key_image_to_rec(Field *field, uchar *ptr, uint len); #endif #endif diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 60df49bd318..8851401d21f 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -222,7 +222,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) Item *expr=item_sum->args[0]; if (expr->real_item()->type() == Item::FIELD_ITEM) { - byte key_buff[MAX_KEY_LENGTH]; + uchar key_buff[MAX_KEY_LENGTH]; TABLE_REF ref; uint range_fl, prefix_len; @@ -366,7 +366,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) Item *expr=item_sum->args[0]; if (expr->real_item()->type() == Item::FIELD_ITEM) { - byte key_buff[MAX_KEY_LENGTH]; + uchar key_buff[MAX_KEY_LENGTH]; TABLE_REF ref; uint range_fl, prefix_len; @@ -660,7 +660,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, less_fl= 1-less_fl; // Convert '<' -> '>' (etc) /* Check if field is part of the tested partial key */ - byte *key_ptr= ref->key_buff; + uchar *key_ptr= ref->key_buff; KEY_PART_INFO *part; for (part= keyinfo->key_part; ; key_ptr+= part++->store_length) @@ -709,15 +709,15 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, if (is_null) { part->field->set_null(); - *key_ptr= (byte) 1; + *key_ptr= (uchar) 1; } else { store_val_in_field(part->field, args[between && max_fl ? 2 : 1], CHECK_FIELD_IGNORE); if (part->null_bit) - *key_ptr++= (byte) test(part->field->is_null()); - part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW); + *key_ptr++= (uchar) test(part->field->is_null()); + part->field->get_key_image(key_ptr, part->length, Field::itRAW); } if (is_field_part) { diff --git a/sql/parse_file.cc b/sql/parse_file.cc index f06c7c15202..5ea49396cb4 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -49,27 +49,27 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) */ switch(*ptr) { case '\\': // escape character - if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\\"))) + if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\\\"))) return TRUE; break; case '\n': // parameter value delimiter - if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\n"))) + if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\n"))) return TRUE; break; case '\0': // problem for some string processing utilities - if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\0"))) + if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\0"))) return TRUE; break; case 26: // problem for windows utilities (Ctrl-Z) - if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\z"))) + if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\z"))) return TRUE; break; case '\'': // list of string delimiter - if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\'"))) + if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\\'"))) return TRUE; break; default: - if (my_b_append(file, (const byte *)ptr, 1)) + if (my_b_append(file, (const uchar *)ptr, 1)) return TRUE; } } @@ -93,7 +93,7 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) */ static my_bool -write_parameter(IO_CACHE *file, gptr base, File_option *parameter, +write_parameter(IO_CACHE *file, uchar* base, File_option *parameter, ulonglong *old_version) { char num_buf[20]; // buffer for numeric operations @@ -105,7 +105,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, case FILE_OPTIONS_STRING: { LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset); - if (my_b_append(file, (const byte *)val_s->str, val_s->length)) + if (my_b_append(file, (const uchar *)val_s->str, val_s->length)) DBUG_RETURN(TRUE); break; } @@ -118,7 +118,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, case FILE_OPTIONS_ULONGLONG: { num.set(*((ulonglong *)(base + parameter->offset)), &my_charset_bin); - if (my_b_append(file, (const byte *)num.ptr(), num.length())) + if (my_b_append(file, (const uchar *)num.ptr(), num.length())) DBUG_RETURN(TRUE); break; } @@ -127,7 +127,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, ulonglong *val_i= (ulonglong *)(base + parameter->offset); *old_version= (*val_i)++; num.set(*val_i, &my_charset_bin); - if (my_b_append(file, (const byte *)num.ptr(), num.length())) + if (my_b_append(file, (const uchar *)num.ptr(), num.length())) DBUG_RETURN(TRUE); break; } @@ -140,7 +140,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH, tm); val_s->length= PARSE_FILE_TIMESTAMPLENGTH; - if (my_b_append(file, (const byte *)val_s->str, + if (my_b_append(file, (const uchar *)val_s->str, PARSE_FILE_TIMESTAMPLENGTH)) DBUG_RETURN(TRUE); break; @@ -154,10 +154,10 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, while ((str= it++)) { // We need ' ' after string to detect list continuation - if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) || - my_b_append(file, (const byte *)STRING_WITH_LEN("\'")) || + if ((!first && my_b_append(file, (const uchar *)STRING_WITH_LEN(" "))) || + my_b_append(file, (const uchar *)STRING_WITH_LEN("\'")) || write_escaped_string(file, str) || - my_b_append(file, (const byte *)STRING_WITH_LEN("\'"))) + my_b_append(file, (const uchar *)STRING_WITH_LEN("\'"))) { DBUG_RETURN(TRUE); } @@ -175,8 +175,8 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, { num.set(*val, &my_charset_bin); // We need ' ' after string to detect list continuation - if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) || - my_b_append(file, (const byte *)num.ptr(), num.length())) + if ((!first && my_b_append(file, (const uchar *)STRING_WITH_LEN(" "))) || + my_b_append(file, (const uchar *)num.ptr(), num.length())) { DBUG_RETURN(TRUE); } @@ -212,7 +212,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, - gptr base, File_option *parameters, + uchar* base, File_option *parameters, uint max_versions) { File handler; @@ -254,19 +254,19 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, goto err_w_file; // write header (file signature) - if (my_b_append(&file, (const byte *)STRING_WITH_LEN("TYPE=")) || - my_b_append(&file, (const byte *)type->str, type->length) || - my_b_append(&file, (const byte *)STRING_WITH_LEN("\n"))) + if (my_b_append(&file, (const uchar *)STRING_WITH_LEN("TYPE=")) || + my_b_append(&file, (const uchar *)type->str, type->length) || + my_b_append(&file, (const uchar *)STRING_WITH_LEN("\n"))) goto err_w_file; // write parameters to temporary file for (param= parameters; param->name.str; param++) { - if (my_b_append(&file, (const byte *)param->name.str, + if (my_b_append(&file, (const uchar *)param->name.str, param->name.length) || - my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) || + my_b_append(&file, (const uchar *)STRING_WITH_LEN("=")) || write_parameter(&file, base, param, &old_version) || - my_b_append(&file, (const byte *)STRING_WITH_LEN("\n"))) + my_b_append(&file, (const uchar *)STRING_WITH_LEN("\n"))) goto err_w_cache; } @@ -423,7 +423,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, bool bad_format_errors) { MY_STAT stat_info; - uint len; + size_t len; char *end, *sign; File_parser *parser; File file; @@ -445,7 +445,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, DBUG_RETURN(0); } - if (!(parser->buff= alloc_root(mem_root, stat_info.st_size+1))) + if (!(parser->buff= (char*) alloc_root(mem_root, stat_info.st_size+1))) { DBUG_RETURN(0); } @@ -455,7 +455,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, DBUG_RETURN(0); } - if ((len= my_read(file, (byte *)parser->buff, + if ((len= my_read(file, (uchar *)parser->buff, stat_info.st_size, MYF(MY_WME))) == MY_FILE_ERROR) { @@ -533,11 +533,8 @@ parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) str->length= eol - ptr; - if (!(str->str= alloc_root(mem_root, str->length+1))) + if (!(str->str= strmake_root(mem_root, ptr, str->length))) return 0; - - memcpy(str->str, ptr, str->length); - str->str[str->length]= '\0'; // just for safety return eol+1; } @@ -623,7 +620,7 @@ parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) char *eol= strchr(ptr, '\n'); if (eol == 0 || eol >= end || - !(str->str= alloc_root(mem_root, (eol - ptr) + 1)) || + !(str->str= (char*) alloc_root(mem_root, (eol - ptr) + 1)) || read_escaped_string(ptr, eol, str)) return 0; @@ -668,7 +665,7 @@ parse_quoted_escaped_string(char *ptr, char *end, // process string if (eol >= end || - !(str->str= alloc_root(mem_root, result_len + 1)) || + !(str->str= (char*) alloc_root(mem_root, result_len + 1)) || read_escaped_string(ptr, eol, str)) return 0; @@ -691,7 +688,7 @@ parse_quoted_escaped_string(char *ptr, char *end, */ bool get_file_options_ulllist(char *&ptr, char *end, char *line, - gptr base, File_option *parameter, + uchar* base, File_option *parameter, MEM_ROOT *mem_root) { List<ulonglong> *nlist= (List<ulonglong>*)(base + parameter->offset); @@ -754,7 +751,7 @@ nlist_err: */ my_bool -File_parser::parse(gptr base, MEM_ROOT *mem_root, +File_parser::parse(uchar* base, MEM_ROOT *mem_root, struct File_option *parameters, uint required, Unknown_key_hook *hook) { @@ -963,7 +960,7 @@ list_err: bool File_parser_dummy_hook::process_unknown_string(char *&unknown_key, - gptr base, MEM_ROOT *mem_root, + uchar* base, MEM_ROOT *mem_root, char *end) { DBUG_ENTER("file_parser_dummy_hook::process_unknown_string"); diff --git a/sql/parse_file.h b/sql/parse_file.h index 21873b32904..91700959681 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -50,7 +50,7 @@ class Unknown_key_hook public: Unknown_key_hook() {} /* Remove gcc warning */ virtual ~Unknown_key_hook() {} /* Remove gcc warning */ - virtual bool process_unknown_string(char *&unknown_key, gptr base, + virtual bool process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, char *end)= 0; }; @@ -61,14 +61,14 @@ class File_parser_dummy_hook: public Unknown_key_hook { public: File_parser_dummy_hook() {} /* Remove gcc warning */ - virtual bool process_unknown_string(char *&unknown_key, gptr base, + virtual bool process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, char *end); }; extern File_parser_dummy_hook file_parser_dummy_hook; bool get_file_options_ulllist(char *&ptr, char *end, char *line, - gptr base, File_option *parameter, + uchar* base, File_option *parameter, MEM_ROOT *mem_root); char * @@ -81,7 +81,7 @@ File_parser *sql_parse_prepare(const LEX_STRING *file_name, my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, - gptr base, File_option *parameters, uint versions); + uchar* base, File_option *parameters, uint versions); my_bool rename_in_schema_file(const char *schema, const char *old_name, const char *new_name, ulonglong revision, uint num_view_backups); @@ -97,7 +97,7 @@ public: my_bool ok() { return content_ok; } LEX_STRING *type() { return &file_type; } - my_bool parse(gptr base, MEM_ROOT *mem_root, + my_bool parse(uchar* base, MEM_ROOT *mem_root, struct File_option *parameters, uint required, Unknown_key_hook *hook); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 3e0257f5b1d..23bc3c96e8f 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -90,10 +90,11 @@ partition_info *partition_info::get_clone() #define MAX_PART_NAME_SIZE 8 -char *partition_info::create_default_partition_names(uint part_no, uint no_parts, +char *partition_info::create_default_partition_names(uint part_no, + uint no_parts, uint start_no) { - char *ptr= sql_calloc(no_parts*MAX_PART_NAME_SIZE); + char *ptr= (char*) sql_calloc(no_parts*MAX_PART_NAME_SIZE); char *move_ptr= ptr; uint i= 0; DBUG_ENTER("create_default_partition_names"); @@ -129,7 +130,7 @@ char *partition_info::create_subpartition_name(uint subpart_no, const char *part_name) { uint size_alloc= strlen(part_name) + MAX_PART_NAME_SIZE; - char *ptr= sql_calloc(size_alloc); + char *ptr= (char*) sql_calloc(size_alloc); DBUG_ENTER("create_subpartition_name"); if (likely(ptr != NULL)) @@ -902,7 +903,7 @@ void partition_info::print_no_partition_found(TABLE *table) bool partition_info::set_up_charset_field_preps() { Field *field, **ptr; - char **char_ptrs; + uchar **char_ptrs; unsigned i; bool found; size_t size; @@ -927,14 +928,14 @@ bool partition_info::set_up_charset_field_preps() } } size= tot_part_fields * sizeof(char*); - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**)sql_calloc(size))) goto error; part_field_buffers= char_ptrs; - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**)sql_calloc(size))) goto error; restore_part_field_ptrs= char_ptrs; size= (tot_part_fields + 1) * sizeof(Field*); - if (!(char_ptrs= (char**)sql_alloc(size))) + if (!(char_ptrs= (uchar**)sql_alloc(size))) goto error; part_charset_field_array= (Field**)char_ptrs; ptr= part_field_array; @@ -943,9 +944,9 @@ bool partition_info::set_up_charset_field_preps() { if (field_is_partition_charset(field)) { - char *field_buf; + uchar *field_buf; size= field->pack_length(); - if (!(field_buf= sql_calloc(size))) + if (!(field_buf= (uchar*) sql_calloc(size))) goto error; part_charset_field_array[i]= field; part_field_buffers[i++]= field_buf; @@ -964,14 +965,14 @@ bool partition_info::set_up_charset_field_preps() tot_subpart_fields++; } size= tot_subpart_fields * sizeof(char*); - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**) sql_calloc(size))) goto error; subpart_field_buffers= char_ptrs; - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**) sql_calloc(size))) goto error; restore_subpart_field_ptrs= char_ptrs; size= (tot_subpart_fields + 1) * sizeof(Field*); - if (!(char_ptrs= (char**)sql_alloc(size))) + if (!(char_ptrs= (uchar**) sql_alloc(size))) goto error; subpart_charset_field_array= (Field**)char_ptrs; i= 0; @@ -979,7 +980,7 @@ bool partition_info::set_up_charset_field_preps() { unsigned j= 0; CHARSET_INFO *cs; - char *field_buf; + uchar *field_buf; LINT_INIT(field_buf); if (!field_is_partition_charset(field)) @@ -995,12 +996,12 @@ bool partition_info::set_up_charset_field_preps() if (!found) { tot_fields++; - if (!(field_buf= sql_calloc(size))) + if (!(field_buf= (uchar*) sql_calloc(size))) goto error; } subpart_field_buffers[i++]= field_buf; } - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**) sql_calloc(size))) goto error; restore_subpart_field_ptrs= char_ptrs; } @@ -1009,14 +1010,14 @@ bool partition_info::set_up_charset_field_preps() uint j,k,l; size= tot_fields*sizeof(char**); - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**)sql_calloc(size))) goto error; full_part_field_buffers= char_ptrs; - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**)sql_calloc(size))) goto error; restore_full_part_field_ptrs= char_ptrs; size= (tot_fields + 1) * sizeof(char**); - if (!(char_ptrs= (char**)sql_calloc(size))) + if (!(char_ptrs= (uchar**)sql_calloc(size))) goto error; full_part_charset_field_array= (Field**)char_ptrs; for (i= 0; i < tot_part_fields; i++) diff --git a/sql/partition_info.h b/sql/partition_info.h index 6c21002c184..ce2f2a7b358 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -87,12 +87,12 @@ public: partition functions we must allocate field buffers for the field of the fields in the partition function. */ - char **part_field_buffers; - char **subpart_field_buffers; - char **full_part_field_buffers; - char **restore_part_field_ptrs; - char **restore_subpart_field_ptrs; - char **restore_full_part_field_ptrs; + uchar **part_field_buffers; + uchar **subpart_field_buffers; + uchar **full_part_field_buffers; + uchar **restore_part_field_ptrs; + uchar **restore_subpart_field_ptrs; + uchar **restore_full_part_field_ptrs; Item *part_expr; Item *subpart_expr; diff --git a/sql/protocol.cc b/sql/protocol.cc index d537fd346f9..2ed241c4c98 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -33,9 +33,9 @@ static void write_eof_packet(THD *thd, NET *net); #endif #ifndef EMBEDDED_LIBRARY -bool Protocol::net_store_data(const char *from, uint length) +bool Protocol::net_store_data(const uchar *from, size_t length) #else -bool Protocol_binary::net_store_data(const char *from, uint length) +bool Protocol_binary::net_store_data(const uchar *from, size_t length) #endif { ulong packet_length=packet->length(); @@ -46,10 +46,9 @@ bool Protocol_binary::net_store_data(const char *from, uint length) if (packet_length+9+length > packet->alloced_length() && packet->realloc(packet_length+9+length)) return 1; - char *to=(char*) net_store_length((char*) packet->ptr()+packet_length, - length); + uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length); memcpy(to,from,length); - packet->length((uint) (to+length-packet->ptr())); + packet->length((uint) (to+length-(uchar*) packet->ptr())); return 0; } @@ -227,7 +226,7 @@ net_printf_error(THD *thd, uint errcode, ...) memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH); } } - VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset)); + VOID(net_real_write(net, net->buff, length+head_length+1+offset)); #else net->last_errno= errcode; strmake(net->last_error, text_pos, length); @@ -271,7 +270,7 @@ void send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) { NET *net= &thd->net; - char buff[MYSQL_ERRMSG_SIZE+10],*pos; + uchar buff[MYSQL_ERRMSG_SIZE+10],*pos; DBUG_ENTER("send_ok"); if (net->no_send_ok || !net->vio) // hack for re-parsing queries @@ -307,8 +306,8 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) pos+=2; } if (message) - pos=net_store_data((char*) pos, message, strlen(message)); - VOID(my_net_write(net,buff,(uint) (pos-buff))); + pos= net_store_data(pos, (uchar*) message, strlen(message)); + VOID(my_net_write(net, buff, (size_t) (pos-buff))); VOID(net_flush(net)); /* We can't anymore send an error to the client */ thd->net.report_error= 0; @@ -318,7 +317,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_VOID_RETURN; } -static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ +static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ /* Send eof (= end of result set) to the client @@ -383,7 +382,7 @@ static void write_eof_packet(THD *thd, NET *net) if (thd->is_fatal_error) thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; int2store(buff+3, thd->server_status); - VOID(my_net_write(net, (char*) buff, 5)); + VOID(my_net_write(net, buff, 5)); } else VOID(my_net_write(net, eof_buff, 1)); @@ -411,7 +410,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) { NET *net= &thd->net; uint length; - char buff[MYSQL_ERRMSG_SIZE+2], *pos; + uchar buff[MYSQL_ERRMSG_SIZE+2], *pos; DBUG_ENTER("send_error_packet"); @@ -433,17 +432,19 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) { /* The first # is to make the protocol backward compatible */ buff[2]= '#'; - pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno)); + pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno)); } - length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff); - err=buff; + length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) - + (char*) buff); + err= (char*) buff; } else { length=(uint) strlen(err); set_if_smaller(length,MYSQL_ERRMSG_SIZE-1); } - VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length)); + VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err, + length)); DBUG_VOID_RETURN; } @@ -459,17 +460,16 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ulonglong for bigger numbers. */ -static char *net_store_length_fast(char *pkg, uint length) +static uchar *net_store_length_fast(uchar *packet, uint length) { - uchar *packet=(uchar*) pkg; if (length < 251) { *packet=(uchar) length; - return (char*) packet+1; + return packet+1; } *packet++=252; int2store(packet,(uint) length); - return (char*) packet+2; + return packet+2; } @@ -480,14 +480,14 @@ static char *net_store_length_fast(char *pkg, uint length) /* The following will only be used for short strings < 65K */ -char *net_store_data(char *to,const char *from, uint length) +uchar *net_store_data(uchar *to, const uchar *from, size_t length) { to=net_store_length_fast(to,length); memcpy(to,from,length); return to+length; } -char *net_store_data(char *to,int32 from) +uchar *net_store_data(uchar *to,int32 from) { char buff[20]; uint length=(uint) (int10_to_str(from,buff,10)-buff); @@ -496,7 +496,7 @@ char *net_store_data(char *to,int32 from) return to+length; } -char *net_store_data(char *to,longlong from) +uchar *net_store_data(uchar *to,longlong from) { char buff[22]; uint length=(uint) (longlong10_to_str(from,buff,10)-buff); @@ -555,7 +555,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) { List_iterator_fast<Item> it(*list); Item *item; - char buff[80]; + uchar buff[80]; String tmp((char*) buff,sizeof(buff),&my_charset_bin); Protocol_text prot(thd); String *local_packet= prot.storage_packet(); @@ -564,8 +564,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags) if (flags & SEND_NUM_ROWS) { // Packet with number of elements - char *pos=net_store_length(buff, list->elements); - (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); + uchar *pos= net_store_length(buff, list->elements); + (void) my_net_write(&thd->net, buff, (size_t) (pos-buff)); } #ifndef DBUG_OFF @@ -698,7 +698,8 @@ err: bool Protocol::write() { DBUG_ENTER("Protocol::write"); - DBUG_RETURN(my_net_write(&thd->net, packet->ptr(), packet->length())); + DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(), + packet->length())); } #endif /* EMBEDDED_LIBRARY */ @@ -785,7 +786,7 @@ bool Protocol_text::store_null() and store in network buffer. */ -bool Protocol::store_string_aux(const char *from, uint length, +bool Protocol::store_string_aux(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { /* 'tocs' is set 0 when client issues SET character_set_results=NULL */ @@ -794,15 +795,15 @@ bool Protocol::store_string_aux(const char *from, uint length, tocs != &my_charset_bin) { uint dummy_errors; - return convert->copy(from, length, fromcs, tocs, &dummy_errors) || - net_store_data(convert->ptr(), convert->length()); + return (convert->copy(from, length, fromcs, tocs, &dummy_errors) || + net_store_data((uchar*) convert->ptr(), convert->length())); } - return net_store_data(from, length); + return net_store_data((uchar*) from, length); } -bool Protocol_text::store(const char *from, uint length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs) +bool Protocol_text::store(const char *from, size_t length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { #ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || @@ -817,7 +818,7 @@ bool Protocol_text::store(const char *from, uint length, } -bool Protocol_text::store(const char *from, uint length, +bool Protocol_text::store(const char *from, size_t length, CHARSET_INFO *fromcs) { CHARSET_INFO *tocs= this->thd->variables.character_set_results; @@ -841,8 +842,8 @@ bool Protocol_text::store_tiny(longlong from) field_pos++; #endif char buff[20]; - return net_store_data((char*) buff, - (uint) (int10_to_str((int) from,buff, -10)-buff)); + return net_store_data((uchar*) buff, + (size_t) (int10_to_str((int) from, buff, -10) - buff)); } @@ -855,8 +856,9 @@ bool Protocol_text::store_short(longlong from) field_pos++; #endif char buff[20]; - return net_store_data((char*) buff, - (uint) (int10_to_str((int) from,buff, -10)-buff)); + return net_store_data((uchar*) buff, + (size_t) (int10_to_str((int) from, buff, -10) - + buff)); } @@ -869,8 +871,9 @@ bool Protocol_text::store_long(longlong from) field_pos++; #endif char buff[20]; - return net_store_data((char*) buff, - (uint) (int10_to_str((long int)from,buff, (from <0)?-10:10)-buff)); + return net_store_data((uchar*) buff, + (size_t) (int10_to_str((long int)from, buff, + (from <0)?-10:10)-buff)); } @@ -882,10 +885,10 @@ bool Protocol_text::store_longlong(longlong from, bool unsigned_flag) field_pos++; #endif char buff[22]; - return net_store_data((char*) buff, - (uint) (longlong10_to_str(from,buff, - unsigned_flag ? 10 : -10)- - buff)); + return net_store_data((uchar*) buff, + (size_t) (longlong10_to_str(from,buff, + unsigned_flag ? 10 : -10)- + buff)); } @@ -899,7 +902,7 @@ bool Protocol_text::store_decimal(const my_decimal *d) char buff[DECIMAL_MAX_STR_LENGTH]; String str(buff, sizeof(buff), &my_charset_bin); (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str); - return net_store_data(str.ptr(), str.length()); + return net_store_data((uchar*) str.ptr(), str.length()); } @@ -911,7 +914,7 @@ bool Protocol_text::store(float from, uint32 decimals, String *buffer) field_pos++; #endif buffer->set_real((double) from, decimals, thd->charset()); - return net_store_data((char*) buffer->ptr(), buffer->length()); + return net_store_data((uchar*) buffer->ptr(), buffer->length()); } @@ -923,7 +926,7 @@ bool Protocol_text::store(double from, uint32 decimals, String *buffer) field_pos++; #endif buffer->set_real(from, decimals, thd->charset()); - return net_store_data((char*) buffer->ptr(), buffer->length()); + return net_store_data((uchar*) buffer->ptr(), buffer->length()); } @@ -979,8 +982,9 @@ bool Protocol_text::store(MYSQL_TIME *tm) (int) tm->minute, (int) tm->second)); if (tm->second_part) - length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part)); - return net_store_data((char*) buff, length); + length+= my_sprintf(buff+length,(buff+length, ".%06d", + (int)tm->second_part)); + return net_store_data((uchar*) buff, length); } @@ -992,8 +996,8 @@ bool Protocol_text::store_date(MYSQL_TIME *tm) field_pos++; #endif char buff[MAX_DATE_STRING_REP_LENGTH]; - int length= my_date_to_str(tm, buff); - return net_store_data(buff, (uint) length); + size_t length= my_date_to_str(tm, buff); + return net_store_data((uchar*) buff, length); } @@ -1020,7 +1024,7 @@ bool Protocol_text::store_time(MYSQL_TIME *tm) (int) tm->second)); if (tm->second_part) length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part)); - return net_store_data((char*) buff, length); + return net_store_data((uchar*) buff, length); } @@ -1057,12 +1061,12 @@ bool Protocol_binary::prepare_for_send(List<Item> *item_list) void Protocol_binary::prepare_for_resend() { packet->length(bit_fields+1); - bzero((char*) packet->ptr(), 1+bit_fields); + bzero((uchar*) packet->ptr(), 1+bit_fields); field_pos=0; } -bool Protocol_binary::store(const char *from, uint length, +bool Protocol_binary::store(const char *from, size_t length, CHARSET_INFO *fromcs) { CHARSET_INFO *tocs= thd->variables.character_set_results; @@ -1070,7 +1074,7 @@ bool Protocol_binary::store(const char *from, uint length, return store_string_aux(from, length, fromcs, tocs); } -bool Protocol_binary::store(const char *from,uint length, +bool Protocol_binary::store(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { field_pos++; diff --git a/sql/protocol.h b/sql/protocol.h index e0672240e0e..46a2b6d36b6 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -35,14 +35,14 @@ protected: #endif uint field_count; #ifndef EMBEDDED_LIBRARY - bool net_store_data(const char *from, uint length); + bool net_store_data(const uchar *from, size_t length); #else - virtual bool net_store_data(const char *from, uint length); + virtual bool net_store_data(const uchar *from, size_t length); char **next_field; MYSQL_FIELD *next_mysql_field; MEM_ROOT *alloc; #endif - bool store_string_aux(const char *from, uint length, + bool store_string_aux(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); public: Protocol() {} @@ -83,8 +83,8 @@ public: virtual bool store_long(longlong from)=0; virtual bool store_longlong(longlong from, bool unsigned_flag)=0; virtual bool store_decimal(const my_decimal *)=0; - virtual bool store(const char *from, uint length, CHARSET_INFO *cs)=0; - virtual bool store(const char *from, uint length, + virtual bool store(const char *from, size_t length, CHARSET_INFO *cs)=0; + virtual bool store(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0; virtual bool store(float from, uint32 decimals, String *buffer)=0; virtual bool store(double from, uint32 decimals, String *buffer)=0; @@ -124,8 +124,8 @@ public: virtual bool store_long(longlong from); virtual bool store_longlong(longlong from, bool unsigned_flag); virtual bool store_decimal(const my_decimal *); - virtual bool store(const char *from, uint length, CHARSET_INFO *cs); - virtual bool store(const char *from, uint length, + virtual bool store(const char *from, size_t length, CHARSET_INFO *cs); + virtual bool store(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); virtual bool store(MYSQL_TIME *time); virtual bool store_date(MYSQL_TIME *time); @@ -151,7 +151,7 @@ public: virtual void prepare_for_resend(); #ifdef EMBEDDED_LIBRARY virtual bool write(); - bool net_store_data(const char *from, uint length); + bool net_store_data(const uchar *from, size_t length); #endif virtual bool store_null(); virtual bool store_tiny(longlong from); @@ -159,8 +159,8 @@ public: virtual bool store_long(longlong from); virtual bool store_longlong(longlong from, bool unsigned_flag); virtual bool store_decimal(const my_decimal *); - virtual bool store(const char *from,uint length, CHARSET_INFO *cs); - virtual bool store(const char *from, uint length, + virtual bool store(const char *from, size_t length, CHARSET_INFO *cs); + virtual bool store(const char *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); virtual bool store(MYSQL_TIME *time); virtual bool store_date(MYSQL_TIME *time); @@ -178,7 +178,7 @@ void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); void send_eof(THD *thd); bool send_old_password_request(THD *thd); -char *net_store_data(char *to,const char *from, uint length); -char *net_store_data(char *to,int32 from); -char *net_store_data(char *to,longlong from); +uchar *net_store_data(uchar *to,const uchar *from, size_t length); +uchar *net_store_data(uchar *to,int32 from); +uchar *net_store_data(uchar *to,longlong from); diff --git a/sql/records.cc b/sql/records.cc index 0fb9f4f9650..81c26da4b4d 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -432,7 +432,7 @@ static int rr_unpack_from_tempfile(READ_RECORD *info) static int rr_from_pointers(READ_RECORD *info) { int tmp; - byte *cache_pos; + uchar *cache_pos; for (;;) { @@ -502,7 +502,7 @@ static int init_rr_cache(THD *thd, READ_RECORD *info) // We have to allocate one more byte to use uint3korr (see comments for it) if (info->cache_records <= 2 || - !(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records* + !(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records* info->struct_length+1, MYF(0)))) DBUG_RETURN(1); @@ -523,7 +523,7 @@ static int rr_from_cache(READ_RECORD *info) ulong length; my_off_t rest_of_file; int16 error; - byte *position,*ref_position,*record_pos; + uchar *position,*ref_position,*record_pos; ulong record; for (;;) @@ -560,7 +560,7 @@ static int rr_from_cache(READ_RECORD *info) ref_position=info->read_positions; for (i=0 ; i < length ; i++,position+=info->ref_length) { - memcpy(ref_position,position,(size_s) info->ref_length); + memcpy(ref_position,position,(size_t) info->ref_length); ref_position+=MAX_REFLENGTH; int3store(ref_position,(long) i); ref_position+=3; @@ -570,7 +570,7 @@ static int rr_from_cache(READ_RECORD *info) position=info->read_positions; for (i=0 ; i < length ; i++) { - memcpy(info->ref_pos,position,(size_s) info->ref_length); + memcpy(info->ref_pos,position,(size_t) info->ref_length); position+=MAX_REFLENGTH; record=uint3korr(position); position+=3; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 6470f15e458..8bab1ff1ca3 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -134,9 +134,9 @@ void unregister_slave(THD* thd, bool only_mine, bool need_mutex) SLAVE_INFO* old_si; if ((old_si = (SLAVE_INFO*)hash_search(&slave_list, - (byte*)&thd->server_id, 4)) && + (uchar*)&thd->server_id, 4)) && (!only_mine || old_si->thd == thd)) - hash_delete(&slave_list, (byte*)old_si); + hash_delete(&slave_list, (uchar*)old_si); if (need_mutex) pthread_mutex_unlock(&LOCK_slave_list); @@ -180,12 +180,12 @@ int register_slave(THD* thd, uchar* packet, uint packet_length) pthread_mutex_lock(&LOCK_slave_list); unregister_slave(thd,0,0); - res= my_hash_insert(&slave_list, (byte*) si); + res= my_hash_insert(&slave_list, (uchar*) si); pthread_mutex_unlock(&LOCK_slave_list); return res; err: - my_free((gptr) si, MYF(MY_WME)); + my_free(si, MYF(MY_WME)); my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave", MYF(0)); err2: @@ -193,7 +193,7 @@ err2: } extern "C" uint32 -*slave_list_key(SLAVE_INFO* si, uint* len, +*slave_list_key(SLAVE_INFO* si, size_t *len, my_bool not_used __attribute__((unused))) { *len = 4; @@ -202,7 +202,7 @@ extern "C" uint32 extern "C" void slave_info_free(void *s) { - my_free((gptr) s, MYF(MY_WME)); + my_free(s, MYF(MY_WME)); } void init_slave_list() @@ -531,7 +531,7 @@ HOSTS"; SLAVE_INFO* si, *old_si; log_server_id = atoi(row[0]); if ((old_si= (SLAVE_INFO*)hash_search(&slave_list, - (byte*)&log_server_id,4))) + (uchar*)&log_server_id,4))) si = old_si; else { @@ -542,7 +542,7 @@ HOSTS"; goto err; } si->server_id = log_server_id; - my_hash_insert(&slave_list, (byte*)si); + my_hash_insert(&slave_list, (uchar*)si); } strmake(si->host, row[1], sizeof(si->host)-1); si->port = atoi(row[port_ind]); diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index f76f798f6a6..bb5db0106eb 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -103,12 +103,12 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables) len= (uint) (strmov(end, tables->table_name) - hash_key); if (do_table_inited) // if there are any do's { - if (hash_search(&do_table, (byte*) hash_key, len)) + if (hash_search(&do_table, (uchar*) hash_key, len)) DBUG_RETURN(1); } if (ignore_table_inited) // if there are any ignores { - if (hash_search(&ignore_table, (byte*) hash_key, len)) + if (hash_search(&ignore_table, (uchar*) hash_key, len)) DBUG_RETURN(0); } if (wild_do_table_inited && @@ -319,7 +319,7 @@ Rpl_filter::add_table_rule(HASH* h, const char* table_spec) e->key_len= len; memcpy(e->db, table_spec, len); - return my_hash_insert(h, (byte*)e); + return my_hash_insert(h, (uchar*)e); } @@ -340,7 +340,7 @@ Rpl_filter::add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec) e->tbl_name= e->db + (dot - table_spec) + 1; e->key_len= len; memcpy(e->db, table_spec, len); - insert_dynamic(a, (gptr)&e); + insert_dynamic(a, (uchar*)&e); return 0; } @@ -363,13 +363,13 @@ Rpl_filter::add_ignore_db(const char* table_spec) } -static byte* get_table_key(const byte* a, uint* len, +static uchar* get_table_key(const uchar* a, size_t *len, my_bool __attribute__((unused))) { TABLE_RULE_ENT *e= (TABLE_RULE_ENT *) a; *len= e->key_len; - return (byte*)e->db; + return (uchar*)e->db; } @@ -377,7 +377,7 @@ static void free_table_ent(void* a) { TABLE_RULE_ENT *e= (TABLE_RULE_ENT *) a; - my_free((gptr) e, MYF(0)); + my_free((uchar*) e, MYF(0)); } @@ -408,7 +408,7 @@ Rpl_filter::find_wild(DYNAMIC_ARRAY *a, const char* key, int len) for (i= 0; i < a->elements; i++) { TABLE_RULE_ENT* e ; - get_dynamic(a, (gptr)&e, i); + get_dynamic(a, (uchar*)&e, i); if (!my_wildcmp(system_charset_info, key, key_end, (const char*)e->db, (const char*)(e->db + e->key_len), @@ -427,7 +427,7 @@ Rpl_filter::free_string_array(DYNAMIC_ARRAY *a) for (i= 0; i < a->elements; i++) { char* p; - get_dynamic(a, (gptr) &p, i); + get_dynamic(a, (uchar*) &p, i); my_free(p, MYF(MY_WME)); } delete_dynamic(a); @@ -474,7 +474,7 @@ Rpl_filter::table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a, for (uint i= 0; i < a->elements; i++) { TABLE_RULE_ENT* e; - get_dynamic(a, (gptr)&e, i); + get_dynamic(a, (uchar*)&e, i); if (s->length()) s->append(','); s->append(e->db,e->key_len); @@ -512,7 +512,7 @@ Rpl_filter::get_wild_ignore_table(String* str) const char* -Rpl_filter::get_rewrite_db(const char* db, uint *new_len) +Rpl_filter::get_rewrite_db(const char* db, size_t *new_len) { if (rewrite_db.is_empty() || !db) return db; diff --git a/sql/rpl_filter.h b/sql/rpl_filter.h index 396207d3a28..ff7e4081bb1 100644 --- a/sql/rpl_filter.h +++ b/sql/rpl_filter.h @@ -69,7 +69,7 @@ public: void get_wild_do_table(String* str); void get_wild_ignore_table(String* str); - const char* get_rewrite_db(const char* db, uint *new_len); + const char* get_rewrite_db(const char* db, size_t *new_len); I_List<i_string>* get_do_db(); I_List<i_string>* get_ignore_db(); diff --git a/sql/rpl_injector.h b/sql/rpl_injector.h index 9c444ee20b3..4ece092c5b8 100644 --- a/sql/rpl_injector.h +++ b/sql/rpl_injector.h @@ -74,7 +74,7 @@ public: friend class injector; public: /* Convenience definitions */ - typedef byte* record_type; + typedef uchar* record_type; typedef uint32 server_id_type; /* diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index bb9d0e6d953..f506a3c319d 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -28,7 +28,8 @@ int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val); MASTER_INFO::MASTER_INFO() - :ssl(0), fd(-1), io_thd(0), inited(0), + :Slave_reporting_capability("I/O"), + ssl(0), fd(-1), io_thd(0), inited(0), abort_slave(0),slave_running(0), ssl_verify_server_cert(0), slave_run_id(0) { diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 08435795a91..44ab0d1dc15 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -19,6 +19,7 @@ #ifdef HAVE_REPLICATION #include "rpl_rli.h" +#include "rpl_reporting.h" /***************************************************************************** @@ -54,7 +55,7 @@ *****************************************************************************/ -class MASTER_INFO +class MASTER_INFO : public Slave_reporting_capability { public: MASTER_INFO(); diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 4c6686cf446..94778948bf9 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -14,6 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysql_priv.h" +#include "rpl_rli.h" #include "rpl_record.h" #include "slave.h" // Need to pull in slave_print_msg @@ -51,14 +52,14 @@ @return The number of bytes written at @c row_data. */ #if !defined(MYSQL_CLIENT) -my_size_t +size_t pack_row(TABLE *table, MY_BITMAP const* cols, - byte *row_data, const byte *record) + uchar *row_data, const uchar *record) { Field **p_field= table->field, *field; int const null_byte_count= (bitmap_bits_set(cols) + 7) / 8; - byte *pack_ptr = row_data + null_byte_count; - byte *null_ptr = row_data; + uchar *pack_ptr = row_data + null_byte_count; + uchar *null_ptr = row_data; my_ptrdiff_t const rec_offset= record - table->record[0]; my_ptrdiff_t const def_offset= table->s->default_values - table->record[0]; @@ -90,7 +91,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, /* We only store the data of the field if it is non-null */ - pack_ptr= (byte*)field->pack((char *) pack_ptr, field->ptr + offset); + pack_ptr= field->pack(pack_ptr, field->ptr + offset); } null_mask <<= 1; @@ -119,7 +120,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, */ DBUG_ASSERT(null_ptr == row_data + null_byte_count); - return static_cast<my_size_t>(pack_ptr - row_data); + return static_cast<size_t>(pack_ptr - row_data); } #endif @@ -164,17 +165,17 @@ pack_row(TABLE *table, MY_BITMAP const* cols, int unpack_row(RELAY_LOG_INFO const *rli, TABLE *table, uint const colcnt, - char const *const row_data, MY_BITMAP const *cols, - char const **const row_end, ulong *const master_reclength, + uchar const *const row_data, MY_BITMAP const *cols, + uchar const **const row_end, ulong *const master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type) { DBUG_ENTER("unpack_row"); DBUG_ASSERT(row_data); - my_size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8; + size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8; int error= 0; - char const *null_ptr= row_data; - char const *pack_ptr= row_data + master_null_byte_count; + uchar const *null_ptr= row_data; + uchar const *pack_ptr= row_data + master_null_byte_count; bitmap_clear_all(rw_set); @@ -239,7 +240,7 @@ unpack_row(RELAY_LOG_INFO const *rli, if (master_reclength) { if (*field_ptr) - *master_reclength = (*field_ptr)->ptr - (char*) table->record[0]; + *master_reclength = (*field_ptr)->ptr - table->record[0]; else *master_reclength = table->s->reclength; } @@ -263,11 +264,11 @@ unpack_row(RELAY_LOG_INFO const *rli, if (event_type == WRITE_ROWS_EVENT && ((*field_ptr)->flags & mask) == mask) { - slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD, - "Field `%s` of table `%s`.`%s` " - "has no default value and cannot be NULL", - (*field_ptr)->field_name, table->s->db.str, - table->s->table_name.str); + rli->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD, + "Field `%s` of table `%s`.`%s` " + "has no default value and cannot be NULL", + (*field_ptr)->field_name, table->s->db.str, + table->s->table_name.str); error = ER_NO_DEFAULT_FOR_FIELD; } else diff --git a/sql/rpl_record.h b/sql/rpl_record.h index 7ff1bbc7c8e..12c2f1fc713 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -17,15 +17,15 @@ #define RPL_RECORD_H #if !defined(MYSQL_CLIENT) -my_size_t pack_row(TABLE* table, MY_BITMAP const* cols, - byte *row_data, const byte *data); +size_t pack_row(TABLE* table, MY_BITMAP const* cols, + uchar *row_data, const uchar *data); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int unpack_row(RELAY_LOG_INFO const *rli, TABLE *table, uint const colcnt, - char const *const row_data, MY_BITMAP const *cols, - char const **const row_end, ulong *const master_reclength, + uchar const *const row_data, MY_BITMAP const *cols, + uchar const **const row_end, ulong *const master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type); #endif diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index 73e2f4e7344..377aec49113 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -1,14 +1,15 @@ #include "mysql_priv.h" +#include "rpl_rli.h" #include "rpl_record_old.h" -my_size_t +size_t pack_row_old(TABLE *table, MY_BITMAP const* cols, - byte *row_data, const byte *record) + uchar *row_data, const uchar *record) { Field **p_field= table->field, *field; int n_null_bytes= table->s->null_bytes; - byte *ptr; + uchar *ptr; uint i; my_ptrdiff_t const rec_offset= record - table->record[0]; my_ptrdiff_t const def_offset= table->s->default_values - table->record[0]; @@ -22,11 +23,11 @@ pack_row_old(TABLE *table, MY_BITMAP const* cols, my_ptrdiff_t const offset= field->is_null(rec_offset) ? def_offset : rec_offset; field->move_field_offset(offset); - ptr= (byte*)field->pack((char *) ptr, field->ptr); + ptr= field->pack(ptr, field->ptr); field->move_field_offset(-offset); } } - return (static_cast<my_size_t>(ptr - row_data)); + return (static_cast<size_t>(ptr - row_data)); } @@ -70,14 +71,14 @@ pack_row_old(TABLE *table, MY_BITMAP const* cols, #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int unpack_row_old(RELAY_LOG_INFO *rli, - TABLE *table, uint const colcnt, byte *record, - char const *row, MY_BITMAP const *cols, - char const **row_end, ulong *master_reclength, + TABLE *table, uint const colcnt, uchar *record, + uchar const *row, MY_BITMAP const *cols, + uchar const **row_end, ulong *master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type) { DBUG_ASSERT(record && row); - my_ptrdiff_t const offset= record - (byte*) table->record[0]; - my_size_t master_null_bytes= table->s->null_bytes; + my_ptrdiff_t const offset= record - (uchar*) table->record[0]; + size_t master_null_bytes= table->s->null_bytes; if (colcnt != table->s->fields) { @@ -108,7 +109,7 @@ unpack_row_old(RELAY_LOG_INFO *rli, Field **const begin_ptr = table->field; Field **field_ptr; - char const *ptr= row + master_null_bytes; + uchar const *ptr= row + master_null_bytes; Field **const end_ptr= begin_ptr + colcnt; for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr) { @@ -130,7 +131,7 @@ unpack_row_old(RELAY_LOG_INFO *rli, if (master_reclength) { if (*field_ptr) - *master_reclength = (*field_ptr)->ptr - (char*) table->record[0]; + *master_reclength = (*field_ptr)->ptr - table->record[0]; else *master_reclength = table->s->reclength; } @@ -157,11 +158,11 @@ unpack_row_old(RELAY_LOG_INFO *rli, if (event_type == WRITE_ROWS_EVENT && ((*field_ptr)->flags & mask) == mask) { - slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD, - "Field `%s` of table `%s`.`%s` " - "has no default value and cannot be NULL", - (*field_ptr)->field_name, table->s->db.str, - table->s->table_name.str); + rli->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD, + "Field `%s` of table `%s`.`%s` " + "has no default value and cannot be NULL", + (*field_ptr)->field_name, table->s->db.str, + table->s->table_name.str); error = ER_NO_DEFAULT_FOR_FIELD; } else diff --git a/sql/rpl_record_old.h b/sql/rpl_record_old.h index 6ddb01de07c..6af61141d47 100644 --- a/sql/rpl_record_old.h +++ b/sql/rpl_record_old.h @@ -17,14 +17,14 @@ #define RPL_RECORD_OLD_H #ifndef MYSQL_CLIENT -my_size_t pack_row_old(TABLE *table, MY_BITMAP const* cols, - byte *row_data, const byte *record); +size_t pack_row_old(TABLE *table, MY_BITMAP const* cols, + uchar *row_data, const uchar *record); #ifdef HAVE_REPLICATION int unpack_row_old(RELAY_LOG_INFO *rli, - TABLE *table, uint const colcnt, byte *record, - char const *row, MY_BITMAP const *cols, - char const **row_end, ulong *master_reclength, + TABLE *table, uint const colcnt, uchar *record, + uchar const *row, MY_BITMAP const *cols, + uchar const **row_end, ulong *master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type); #endif diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc new file mode 100644 index 00000000000..28f257790c7 --- /dev/null +++ b/sql/rpl_reporting.cc @@ -0,0 +1,48 @@ + +#include "mysql_priv.h" +#include "rpl_reporting.h" + +void +Slave_reporting_capability::report(loglevel level, int err_code, + const char *msg, ...) const +{ + void (*report_function)(const char *, ...); + char buff[MAX_SLAVE_ERRMSG]; + char *pbuff= buff; + uint pbuffsize= sizeof(buff); + va_list args; + va_start(args, msg); + + switch (level) + { + case ERROR_LEVEL: + /* + It's an error, it must be reported in Last_error and Last_errno in SHOW + SLAVE STATUS. + */ + pbuff= m_last_error.message; + pbuffsize= sizeof(m_last_error.message); + m_last_error.number = err_code; + report_function= sql_print_error; + break; + case WARNING_LEVEL: + report_function= sql_print_warning; + break; + case INFORMATION_LEVEL: + report_function= sql_print_information; + break; + default: + DBUG_ASSERT(0); // should not come here + return; // don't crash production builds, just do nothing + } + + my_vsnprintf(pbuff, pbuffsize, msg, args); + + va_end(args); + + /* If the msg string ends with '.', do not add a ',' it would be ugly */ + report_function("Slave %s: %s%s Error_code: %d", + m_thread_name, pbuff, + (pbuff[0] && *(strend(pbuff)-1) == '.') ? "" : ",", + err_code); +} diff --git a/sql/rpl_reporting.h b/sql/rpl_reporting.h new file mode 100644 index 00000000000..2e3fa3cea83 --- /dev/null +++ b/sql/rpl_reporting.h @@ -0,0 +1,85 @@ +#ifndef RPL_REPORTING_H +#define RPL_REPORTING_H + +/** + Maximum size of an error message from a slave thread. + */ +#define MAX_SLAVE_ERRMSG 1024 + +/** + Mix-in to handle the message logging and reporting for relay log + info and master log info structures. + + By inheriting from this class, the class is imbued with + capabilities to do slave reporting. + */ +class Slave_reporting_capability +{ +public: + /** + Constructor. + + @param thread_name Printable name of the slave thread that is reporting. + */ + Slave_reporting_capability(char const *thread_name) + : m_thread_name(thread_name) + { + } + + /** + Writes a message and, if it's an error message, to Last_Error + (which will be displayed by SHOW SLAVE STATUS). + + @param level The severity level + @param err_code The error code + @param msg The message (usually related to the error + code, but can contain more information), in + printf() format. + */ + void report(loglevel level, int err_code, const char *msg, ...) const + ATTRIBUTE_FORMAT(printf, 4, 5); + + /** + Clear errors. They will not show up under <code>SHOW SLAVE + STATUS</code>. + */ + void clear_error() { + m_last_error.clear(); + } + + /** + Error information structure. + */ + class Error { + friend class Slave_reporting_capability; + public: + Error() + { + clear(); + } + + void clear() + { + number= 0; + message[0]= '\0'; + } + + /** Error code */ + uint32 number; + /** Error message */ + char message[MAX_SLAVE_ERRMSG]; + }; + + Error const& last_error() const { return m_last_error; } + +private: + /** + Last error produced by the I/O or SQL thread respectively. + */ + mutable Error m_last_error; + + char const *const m_thread_name; +}; + +#endif // RPL_REPORTING_H + diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 702dec72f56..41df3f63825 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -30,11 +30,12 @@ int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, st_relay_log_info::st_relay_log_info() - :no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), + :Slave_reporting_capability("SQL"), + no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0), - abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0), + abort_pos_wait(0), slave_run_id(0), sql_thd(0), inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), tables_to_lock(0), tables_to_lock_count(0), @@ -44,7 +45,7 @@ st_relay_log_info::st_relay_log_info() group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; - last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0; + until_log_name[0]= ign_master_log_name_end[0]= 0; bzero((char*) &info_file, sizeof(info_file)); bzero((char*) &cache_buf, sizeof(cache_buf)); cached_charset_invalidate(); @@ -337,16 +338,6 @@ static int count_relay_log_space(RELAY_LOG_INFO* rli) } -void st_relay_log_info::clear_slave_error() -{ - DBUG_ENTER("clear_slave_error"); - - /* Clear the errors displayed by SHOW SLAVE STATUS */ - last_slave_error[0]= 0; - last_slave_errno= 0; - DBUG_VOID_RETURN; -} - /* Reset UNTIL condition for RELAY_LOG_INFO @@ -1078,7 +1069,8 @@ bool st_relay_log_info::cached_charset_compare(char *charset) const { DBUG_ENTER("st_relay_log_info::cached_charset_compare"); - if (bcmp(cached_charset, charset, sizeof(cached_charset))) + if (bcmp((uchar*) cached_charset, (uchar*) charset, + sizeof(cached_charset))) { memcpy(const_cast<char*>(cached_charset), charset, sizeof(cached_charset)); DBUG_RETURN(1); @@ -1168,7 +1160,7 @@ void st_relay_log_info::clear_tables_to_lock() { while (tables_to_lock) { - gptr to_free= reinterpret_cast<gptr>(tables_to_lock); + uchar* to_free= reinterpret_cast<uchar*>(tables_to_lock); if (tables_to_lock->m_tabledef_valid) { tables_to_lock->m_tabledef.table_def::~table_def(); diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fada45722f6..c458318594a 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -16,9 +16,8 @@ #ifndef RPL_RLI_H #define RPL_RLI_H -#define MAX_SLAVE_ERRMSG 1024 - #include "rpl_tblmap.h" +#include "rpl_reporting.h" struct RPL_TABLE_LIST; @@ -49,7 +48,7 @@ struct RPL_TABLE_LIST; *****************************************************************************/ -typedef struct st_relay_log_info +typedef struct st_relay_log_info : public Slave_reporting_capability { /** Flags for the state of the replication. @@ -186,7 +185,6 @@ typedef struct st_relay_log_info time_t last_master_timestamp; - void clear_slave_error(); void clear_until_condition(); /* @@ -200,11 +198,9 @@ typedef struct st_relay_log_info pthread_mutex_t log_space_lock; pthread_cond_t log_space_cond; THD * sql_thd; - int last_slave_errno; #ifndef DBUG_OFF int events_till_abort; #endif - char last_slave_error[MAX_SLAVE_ERRMSG]; /* if not set, the value of other members of the structure are undefined */ bool inited; diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc index 7df4bcbdde7..6c8b494dfa9 100644 --- a/sql/rpl_tblmap.cc +++ b/sql/rpl_tblmap.cc @@ -104,11 +104,11 @@ int table_mapping::set_table(ulong table_id, TABLE* table) m_free= m_free->next; } else - hash_delete(&m_table_ids,(byte *)e); + hash_delete(&m_table_ids,(uchar *)e); e->table_id= table_id; e->table= table; - my_hash_insert(&m_table_ids,(byte *)e); + my_hash_insert(&m_table_ids,(uchar *)e); DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)", table_id, (long) e->table, @@ -121,7 +121,7 @@ int table_mapping::remove_table(ulong table_id) entry *e= find_entry(table_id); if (e) { - hash_delete(&m_table_ids,(byte *)e); + hash_delete(&m_table_ids,(uchar *)e); /* we add this entry to the chain of free (free for use) entries */ e->next= m_free; m_free= e; diff --git a/sql/rpl_tblmap.h b/sql/rpl_tblmap.h index dbc968d0f67..446833d5ed6 100644 --- a/sql/rpl_tblmap.h +++ b/sql/rpl_tblmap.h @@ -85,7 +85,7 @@ private: entry *find_entry(ulong table_id) { return (entry *)hash_search(&m_table_ids, - (byte*)&table_id, + (uchar*)&table_id, sizeof(table_id)); } int expand(); diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 1d7cc808f0c..a04bcd1fab9 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -14,10 +14,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rpl_utility.h" +#include "rpl_rli.h" uint32 field_length_from_packed(enum_field_types const field_type, - byte const *const data) + uchar const *const data) { uint32 length; @@ -128,11 +129,13 @@ table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) { DBUG_ASSERT(tsh->db.str && tsh->table_name.str); error= 1; - slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, - "Table width mismatch - " - "received %u columns, %s.%s has %u columns", - (uint) size(), tsh->db.str, tsh->table_name.str, - tsh->fields); + char buf[256]; + my_snprintf(buf, sizeof(buf), "Table width mismatch - " + "received %u columns, %s.%s has %u columns", + (uint) size(), tsh->db.str, tsh->table_name.str, + tsh->fields); + rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, + ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); } for (uint col= 0 ; col < cols_to_check ; ++col) @@ -142,11 +145,13 @@ table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) DBUG_ASSERT(col < size() && col < tsh->fields); DBUG_ASSERT(tsh->db.str && tsh->table_name.str); error= 1; - slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, - "Column %d type mismatch - " - "received type %d, %s.%s has type %d", - col, type(col), tsh->db.str, tsh->table_name.str, - table->field[col]->type()); + char buf[256]; + my_snprintf(buf, sizeof(buf), "Column %d type mismatch - " + "received type %d, %s.%s has type %d", + col, type(col), tsh->db.str, tsh->table_name.str, + table->field[col]->type()); + rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, + ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); } } diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index 82992eec690..2ce8def4577 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -26,7 +26,7 @@ struct st_relay_log_info; typedef st_relay_log_info RELAY_LOG_INFO; uint32 -field_length_from_packed(enum_field_types field_type, byte const *data); +field_length_from_packed(enum_field_types field_type, uchar const *data); /** A table definition from the master. @@ -58,7 +58,7 @@ public: @param types Array of types @param size Number of elements in array 'types' */ - table_def(field_type *types, my_size_t size) + table_def(field_type *types, ulong size) : m_size(size), m_type(new unsigned char [size]) { if (m_type) @@ -81,7 +81,7 @@ public: @return The number of fields that there is type data for. */ - my_size_t size() const { return m_size; } + ulong size() const { return m_size; } /* @@ -93,10 +93,9 @@ public: <code>index</code>. Currently, only the type identifier is returned. */ - field_type type(my_ptrdiff_t index) const + field_type type(ulong index) const { - DBUG_ASSERT(0 <= index); - DBUG_ASSERT(static_cast<my_size_t>(index) < m_size); + DBUG_ASSERT(index < m_size); return m_type[index]; } @@ -120,7 +119,7 @@ public: int compatible_with(RELAY_LOG_INFO const *rli, TABLE *table) const; private: - my_size_t m_size; // Number of elements in the types array + ulong m_size; // Number of elements in the types array field_type *m_type; // Array of type descriptors }; diff --git a/sql/set_var.cc b/sql/set_var.cc index 3dc8cddcb26..d9869ce6809 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -122,9 +122,9 @@ static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); -static byte *get_error_count(THD *thd); -static byte *get_warning_count(THD *thd); -static byte *get_tmpdir(THD *thd); +static uchar *get_error_count(THD *thd); +static uchar *get_warning_count(THD *thd); +static uchar *get_tmpdir(THD *thd); static int sys_check_log_path(THD *thd, set_var *var); static bool sys_update_general_log_path(THD *thd, set_var * var); static void sys_default_general_log_path(THD *thd, enum_var_type type); @@ -699,8 +699,6 @@ static SHOW_VAR fixed_vars[]= { #ifdef HAVE_SYS_UN_H {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, #endif - {"table_definition_cache", (char*) &table_def_size, SHOW_LONG}, - {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG }, #ifdef HAVE_THR_SETCONCURRENCY {"thread_concurrency", (char*) &concurrency, SHOW_LONG}, #endif @@ -788,7 +786,7 @@ static void sys_default_init_slave(THD* thd, enum_var_type type) static int sys_check_ftb_syntax(THD *thd, set_var *var) { if (thd->security_ctx->master_access & SUPER_ACL) - return (ft_boolean_check_syntax_string((byte*) + return (ft_boolean_check_syntax_string((uchar*) var->value->str_value.c_ptr()) ? -1 : 0); else @@ -824,7 +822,11 @@ static void sys_default_ftb_syntax(THD *thd, enum_var_type type) static void fix_low_priority_updates(THD *thd, enum_var_type type) { - if (type != OPT_GLOBAL) + if (type == OPT_GLOBAL) + thr_upgraded_concurrent_insert_lock= + (global_system_variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE); + else thd->update_lock_default= (thd->variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE); } @@ -902,14 +904,14 @@ static int check_completion_type(THD *thd, set_var *var) static void fix_net_read_timeout(THD *thd, enum_var_type type) { if (type != OPT_GLOBAL) - net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); + my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); } static void fix_net_write_timeout(THD *thd, enum_var_type type) { if (type != OPT_GLOBAL) - net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); + my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); } static void fix_net_retry_count(THD *thd, enum_var_type type) @@ -933,12 +935,19 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)), static void fix_query_cache_size(THD *thd, enum_var_type type) { #ifdef HAVE_QUERY_CACHE - ulong requested= query_cache_size; - query_cache.resize(query_cache_size); - if (requested != query_cache_size) + ulong new_cache_size= query_cache.resize(query_cache_size); + + /* + Note: query_cache_size is a global variable reflecting the + requested cache size. See also query_cache_size_arg + */ + + if (query_cache_size != new_cache_size) push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), - requested, query_cache_size); + query_cache_size, new_cache_size); + + query_cache_size= new_cache_size; #endif } @@ -1000,17 +1009,6 @@ bool sys_var_thd_binlog_format::is_readonly() const my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); return 1; } -#ifdef HAVE_NDB_BINLOG - /* - Cluster does not support changing the binlog format on the fly yet. - */ - LEX_STRING ndb_name= {(char*)STRING_WITH_LEN("ndbcluster")}; - if (opt_bin_log && plugin_is_ready(&ndb_name, MYSQL_STORAGE_ENGINE_PLUGIN)) - { - my_error(ER_NDB_CANT_SWITCH_BINLOG_FORMAT, MYF(0)); - return 1; - } -#endif /* HAVE_NDB_BINLOG */ return sys_var_thd_enum::is_readonly(); } @@ -1172,9 +1170,9 @@ bool sys_var_enum::update(THD *thd, set_var *var) } -byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) +uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte*) enum_names->type_names[*value]; + return (uchar*) enum_names->type_names[*value]; } bool sys_var_thd_ulong::check(THD *thd, set_var *var) @@ -1219,12 +1217,12 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type == OPT_GLOBAL) - return (byte*) &(global_system_variables.*offset); - return (byte*) &(thd->variables.*offset); + return (uchar*) &(global_system_variables.*offset); + return (uchar*) &(thd->variables.*offset); } @@ -1265,12 +1263,12 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type == OPT_GLOBAL) - return (byte*) &(global_system_variables.*offset); - return (byte*) &(thd->variables.*offset); + return (uchar*) &(global_system_variables.*offset); + return (uchar*) &(thd->variables.*offset); } bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) @@ -1308,12 +1306,12 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type == OPT_GLOBAL) - return (byte*) &(global_system_variables.*offset); - return (byte*) &(thd->variables.*offset); + return (uchar*) &(global_system_variables.*offset); + return (uchar*) &(thd->variables.*offset); } @@ -1336,12 +1334,12 @@ void sys_var_thd_bool::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type == OPT_GLOBAL) - return (byte*) &(global_system_variables.*offset); - return (byte*) &(thd->variables.*offset); + return (uchar*) &(global_system_variables.*offset); + return (uchar*) &(thd->variables.*offset); } @@ -1489,6 +1487,25 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) pthread_mutex_unlock(&LOCK_global_system_variables); return new Item_int(value,1); } + case SHOW_CHAR_PTR: + { + Item *tmp; + pthread_mutex_lock(&LOCK_global_system_variables); + char *str= *(char**) value_ptr(thd, var_type, base); + if (str) + { + uint length= strlen(str); + tmp= new Item_string(thd->strmake(str, length), length, + system_charset_info, DERIVATION_SYSCONST); + } + else + { + tmp= new Item_null(); + tmp->collation.set(system_charset_info, DERIVATION_SYSCONST); + } + pthread_mutex_unlock(&LOCK_global_system_variables); + return tmp; + } case SHOW_CHAR: { Item *tmp; @@ -1531,13 +1548,13 @@ void sys_var_thd_enum::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { ulong tmp= ((type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset); - return (byte*) enum_names->type_names[tmp]; + return (uchar*) enum_names->type_names[tmp]; } bool sys_var_thd_bit::check(THD *thd, set_var *var) @@ -1553,7 +1570,7 @@ bool sys_var_thd_bit::update(THD *thd, set_var *var) } -byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { /* @@ -1562,7 +1579,7 @@ byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, */ thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ? !reverse : reverse); - return (byte*) &thd->sys_var_tmp.my_bool_value; + return (uchar*) &thd->sys_var_tmp.my_bool_value; } @@ -1573,7 +1590,7 @@ void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type, { DATE_TIME_FORMAT *old; DBUG_ENTER("sys_var_date_time_format::update2"); - DBUG_DUMP("positions",(char*) new_value->positions, + DBUG_DUMP("positions", (uchar*) new_value->positions, sizeof(new_value->positions)); if (type == OPT_GLOBAL) @@ -1653,7 +1670,7 @@ void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type == OPT_GLOBAL) @@ -1666,9 +1683,9 @@ byte *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type, */ res= thd->strmake((global_system_variables.*offset)->format.str, (global_system_variables.*offset)->format.length); - return (byte*) res; + return (uchar*) res; } - return (byte*) (thd->variables.*offset)->format.str; + return (uchar*) (thd->variables.*offset)->format.str; } @@ -1789,11 +1806,11 @@ bool sys_var_character_set::update(THD *thd, set_var *var) } -byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_character_set::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { CHARSET_INFO *cs= ci_ptr(thd,type)[0]; - return cs ? (byte*) cs->csname : (byte*) NULL; + return cs ? (uchar*) cs->csname : (uchar*) NULL; } @@ -1863,11 +1880,12 @@ void sys_var_collation_sv::set_default(THD *thd, enum_var_type type) } -byte *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) +uchar *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.*offset : thd->variables.*offset); - return cs ? (byte*) cs->name : (byte*) "NULL"; + global_system_variables.*offset : thd->variables.*offset); + return cs ? (uchar*) cs->name : (uchar*) "NULL"; } @@ -1885,13 +1903,13 @@ KEY_CACHE *get_key_cache(LEX_STRING *cache_name) } -byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { KEY_CACHE *key_cache= get_key_cache(base); if (!key_cache) key_cache= &zero_key_cache; - return (byte*) key_cache + offset ; + return (uchar*) key_cache + offset ; } @@ -2077,11 +2095,12 @@ static int sys_check_log_path(THD *thd, set_var *var) } else { + size_t path_length; /* Check if directory exists and we have permission to create file & write to file */ - (void) dirname_part(path, var_path); + (void) dirname_part(path, var_path, &path_length); if (my_access(path, (F_OK|W_OK))) return -1; } @@ -2207,7 +2226,7 @@ void sys_var_log_output::set_default(THD *thd, enum_var_type type) } -byte *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { char buff[256]; @@ -2228,7 +2247,7 @@ byte *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, if ((length= tmp.length())) length--; - return (byte*) thd->strmake(tmp.ptr(), length); + return (uchar*) thd->strmake(tmp.ptr(), length); } @@ -2267,11 +2286,11 @@ void sys_var_timestamp::set_default(THD *thd, enum_var_type type) } -byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { thd->sys_var_tmp.long_value= (long) thd->start_time; - return (byte*) &thd->sys_var_tmp.long_value; + return (uchar*) &thd->sys_var_tmp.long_value; } @@ -2283,7 +2302,7 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var) } -byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { /* @@ -2292,7 +2311,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, */ thd->sys_var_tmp.ulonglong_value= thd->read_first_successful_insert_id_in_prev_stmt(); - return (byte*) &thd->sys_var_tmp.ulonglong_value; + return (uchar*) &thd->sys_var_tmp.ulonglong_value; } @@ -2303,12 +2322,12 @@ bool sys_var_insert_id::update(THD *thd, set_var *var) } -byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { thd->sys_var_tmp.ulonglong_value= thd->auto_inc_intervals_forced.minimum(); - return (byte*) &thd->sys_var_tmp.ulonglong_value; + return (uchar*) &thd->sys_var_tmp.ulonglong_value; } @@ -2355,7 +2374,7 @@ bool sys_var_thd_time_zone::update(THD *thd, set_var *var) } -byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { /* @@ -2363,7 +2382,7 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, time zone name is guaranteed to be zero ended. */ if (type == OPT_GLOBAL) - return (byte *)(global_system_variables.time_zone->get_name()->ptr()); + return (uchar *)(global_system_variables.time_zone->get_name()->ptr()); else { /* @@ -2375,7 +2394,7 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, (binlog code stores session value only). */ thd->time_zone_used= 1; - return (byte *)(thd->variables.time_zone->get_name()->ptr()); + return (uchar *)(thd->variables.time_zone->get_name()->ptr()); } } @@ -2437,13 +2456,13 @@ void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type) } -byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { if (type != OPT_GLOBAL && thd->user_connect && thd->user_connect->user_resources.user_conn) - return (byte*) &(thd->user_connect->user_resources.user_conn); - return (byte*) &(max_user_connections); + return (uchar*) &(thd->user_connect->user_resources.user_conn); + return (uchar*) &(max_user_connections); } @@ -2494,12 +2513,12 @@ bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var) } -byte *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { return type == OPT_GLOBAL ? - (byte *) global_system_variables.lc_time_names->name : - (byte *) thd->variables.lc_time_names->name; + (uchar *) global_system_variables.lc_time_names->name : + (uchar *) thd->variables.lc_time_names->name; } @@ -2608,20 +2627,20 @@ static int check_pseudo_thread_id(THD *thd, set_var *var) #endif } -static byte *get_warning_count(THD *thd) +static uchar *get_warning_count(THD *thd) { thd->sys_var_tmp.long_value= (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]); - return (byte*) &thd->sys_var_tmp.long_value; + return (uchar*) &thd->sys_var_tmp.long_value; } -static byte *get_error_count(THD *thd) +static uchar *get_error_count(THD *thd) { thd->sys_var_tmp.long_value= thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR]; - return (byte*) &thd->sys_var_tmp.long_value; + return (uchar*) &thd->sys_var_tmp.long_value; } @@ -2642,11 +2661,11 @@ static byte *get_error_count(THD *thd) RETURN VALUES ptr pointer to NUL-terminated string */ -static byte *get_tmpdir(THD *thd) +static uchar *get_tmpdir(THD *thd) { if (opt_mysql_tmpdir) - return (byte *)opt_mysql_tmpdir; - return (byte*)mysql_tmpdir; + return (uchar *)opt_mysql_tmpdir; + return (uchar*)mysql_tmpdir; } /**************************************************************************** @@ -2692,11 +2711,11 @@ static struct my_option *find_option(struct my_option *opt, const char *name) Return variable name and length for hashing of variables */ -static byte *get_sys_var_length(const sys_var *var, uint *length, - my_bool first) +static uchar *get_sys_var_length(const sys_var *var, size_t *length, + my_bool first) { *length= var->name_length; - return (byte*) var->name; + return (uchar*) var->name; } @@ -2713,6 +2732,7 @@ static byte *get_sys_var_length(const sys_var *var, uint *length, otherwise FAILURE */ + int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options) { sys_var *var; @@ -2723,7 +2743,7 @@ int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options) { var->name_length= strlen(var->name); /* this fails if there is a conflicting variable name. see HASH_UNIQUE */ - if (my_hash_insert(&system_variable_hash, (byte*) var)) + if (my_hash_insert(&system_variable_hash, (uchar*) var)) goto error; if (long_options) var->option_limits= find_option(long_options, var->name); @@ -2732,42 +2752,42 @@ int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options) error: for (; first != var; first= first->next) - hash_delete(&system_variable_hash, (byte*) first); + hash_delete(&system_variable_hash, (uchar*) first); return 1; } - - + + /* Remove variables to the dynamic hash of system variables - + SYNOPSIS mysql_del_sys_var_chain() first Pointer to first system variable to remove - + RETURN VALUES 0 SUCCESS otherwise FAILURE */ - + int mysql_del_sys_var_chain(sys_var *first) { int result= 0; - + /* A write lock should be held on LOCK_system_variables_hash */ - + for (sys_var *var= first; var; var= var->next) - result|= hash_delete(&system_variable_hash, (byte*) var); + result|= hash_delete(&system_variable_hash, (uchar*) var); return result; } - - + + static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) { return strcmp(a->name, b->name); } - - + + /* Constructs an array of system variables for display to the user. @@ -2884,7 +2904,7 @@ void set_var_free() int mysql_append_static_vars(const SHOW_VAR *show_vars, uint count) { for (; count > 0; count--, show_vars++) - if (insert_dynamic(&fixed_show_vars, (char*) show_vars)) + if (insert_dynamic(&fixed_show_vars, (uchar*) show_vars)) return 1; return 0; } @@ -2913,7 +2933,7 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) A lock on LOCK_system_variable_hash should be held */ var= (sys_var*) hash_search(&system_variable_hash, - (byte*) str, length ? length : strlen(str)); + (uchar*) str, length ? length : strlen(str)); if (!(var || no_error)) my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); @@ -3206,10 +3226,10 @@ err: } -byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - byte* result; + uchar* result; handlerton *hton; LEX_STRING *name; plugin_ref plugin= thd->variables.*offset; @@ -3217,7 +3237,7 @@ byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, plugin= my_plugin_lock(thd, &(global_system_variables.*offset)); hton= plugin_data(plugin, handlerton*); name= &hton2plugin[hton->slot]->name; - result= (byte *) thd->strmake(name->str, name->length); + result= (uchar *) thd->strmake(name->str, name->length); if (type == OPT_GLOBAL) plugin_unlock(thd, plugin); return result; @@ -3319,14 +3339,14 @@ symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) } -byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { LEX_STRING sql_mode; ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset); (void) symbolic_mode_representation(thd, val, &sql_mode); - return (byte *) sql_mode.str; + return (uchar *) sql_mode.str; } @@ -3417,7 +3437,7 @@ ulong fix_sql_mode(ulong sql_mode) Named list handling ****************************************************************************/ -gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length, +uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length, NAMED_LIST **found) { I_List_iterator<NAMED_LIST> it(*list); @@ -3436,7 +3456,7 @@ gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length, void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char *name, gptr)) + void (*free_element)(const char *name, uchar*)) { NAMED_LIST *element; DBUG_ENTER("delete_elements"); @@ -3460,7 +3480,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length) if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE), MYF(MY_ZEROFILL | MY_WME)))) { - if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache)) + if (!new NAMED_LIST(&key_caches, name, length, (uchar*) key_cache)) { my_free((char*) key_cache, MYF(0)); key_cache= 0; @@ -3619,14 +3639,14 @@ bool sys_var_thd_dbug::update(THD *thd, set_var *var) } -byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b) +uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b) { char buf[256]; if (type == OPT_GLOBAL) DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); else DBUG_EXPLAIN(buf, sizeof(buf)); - return (byte*) thd->strdup(buf); + return (uchar*) thd->strdup(buf); } @@ -3669,10 +3689,10 @@ sys_var_event_scheduler::update(THD *thd, set_var *var) } -byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type, +uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte *) Events::get_opt_event_scheduler_str(); + return (uchar *) Events::get_opt_event_scheduler_str(); } diff --git a/sql/set_var.h b/sql/set_var.h index 5556e9c9587..a998dc93b84 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -36,7 +36,7 @@ typedef int (*sys_check_func)(THD *, set_var *); typedef bool (*sys_update_func)(THD *, set_var *); typedef void (*sys_after_update_func)(THD *,enum_var_type); typedef void (*sys_set_default_func)(THD *, enum_var_type); -typedef byte *(*sys_value_ptr_func)(THD *thd); +typedef uchar *(*sys_value_ptr_func)(THD *thd); struct sys_var_chain { @@ -73,7 +73,7 @@ public: virtual bool update(THD *thd, set_var *var)=0; virtual void set_default(THD *thd_arg, enum_var_type type) {} virtual SHOW_TYPE show_type() { return SHOW_UNDEF; } - virtual byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + virtual uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { return 0; } virtual bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } /* Error if not GLOBAL */ @@ -123,8 +123,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (byte*) value; } + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (uchar*) value; } }; @@ -154,8 +154,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (byte*) value; } + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (uchar*) value; } }; @@ -173,8 +173,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (byte*) value; } + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (uchar*) value; } bool check_update_type(Item_result type) { return 0; } }; @@ -216,8 +216,8 @@ public: (*set_default_func)(thd, type); } SHOW_TYPE show_type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (byte*) value; } + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (uchar*) value; } bool check_update_type(Item_result type) { return type != STRING_RESULT; /* Only accept strings */ @@ -242,9 +242,9 @@ public: return 1; } SHOW_TYPE show_type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte*) value; + return (uchar*) value; } bool check_update_type(Item_result type) { @@ -271,9 +271,9 @@ public: return 1; } SHOW_TYPE show_type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte*) *value; + return (uchar*) *value; } bool check_update_type(Item_result type) { @@ -299,7 +299,7 @@ public: } bool update(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_update_type(Item_result type) { return 0; } }; @@ -335,7 +335,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -355,7 +355,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_HA_ROWS; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -377,7 +377,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_default(enum_var_type type) { return type == OPT_GLOBAL && !option_limits; @@ -403,7 +403,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check(THD *thd, set_var *var) { return check_enum(thd, var, &bool_typelib); @@ -446,7 +446,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_update_type(Item_result type) { return 0; } }; @@ -466,7 +466,7 @@ public: return check_set(thd, var, enum_names); } void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, LEX_STRING *rep); }; @@ -489,7 +489,7 @@ public: } void set_default(THD *thd, enum_var_type type); bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; class sys_var_thd_table_type :public sys_var_thd_storage_engine @@ -522,7 +522,7 @@ public: bool check_update_type(Item_result type) { return 0; } bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; class sys_var_thd_dbug :public sys_var_thd @@ -536,7 +536,7 @@ public: SHOW_TYPE show_type() { return SHOW_CHAR; } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type) { DBUG_POP(); } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *b); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *b); }; @@ -554,7 +554,7 @@ public: bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } bool check_default(enum_var_type type) { return 0; } SHOW_TYPE show_type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -567,7 +567,7 @@ public: bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE show_type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -580,7 +580,7 @@ public: bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE show_type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -644,23 +644,22 @@ public: } bool check_default(enum_var_type type) { return 0; } bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); virtual void set_default(THD *thd, enum_var_type type)= 0; virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0; }; - class sys_var_character_set_sv :public sys_var_character_set { CHARSET_INFO *SV::*offset; CHARSET_INFO **global_default; public: sys_var_character_set_sv(sys_var_chain *chain, const char *name_arg, - CHARSET_INFO *SV::*offset_arg, - CHARSET_INFO **global_default_arg, - bool is_nullable= 0) + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg, + bool is_nullable= 0) : sys_var_character_set(name_arg, is_nullable), - offset(offset_arg), global_default(global_default_arg) + offset(offset_arg), global_default(global_default_arg) { chain_sys_var(chain); } void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); @@ -683,16 +682,16 @@ class sys_var_collation_sv :public sys_var_collation CHARSET_INFO **global_default; public: sys_var_collation_sv(sys_var_chain *chain, const char *name_arg, - CHARSET_INFO *SV::*offset_arg, - CHARSET_INFO **global_default_arg) + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg) :sys_var_collation(name_arg), - offset(offset_arg), global_default(global_default_arg) + offset(offset_arg), global_default(global_default_arg) { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -705,7 +704,7 @@ public: size_t offset_arg) :sys_var(name_arg), offset(offset_arg) { chain_sys_var(chain); } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_default(enum_var_type type) { return 1; } bool is_struct() { return 1; } }; @@ -754,7 +753,7 @@ public: bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); void update2(THD *thd, enum_var_type type, DATE_TIME_FORMAT *new_value); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); void set_default(THD *thd, enum_var_type type); }; @@ -785,7 +784,7 @@ public: return check_set(thd, var, enum_names); } bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_update_type(Item_result type) { return 0; } void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_CHAR; } @@ -810,7 +809,7 @@ public: bool check_default(enum_var_type type) { return 1; } bool check_type(enum_var_type type) { return type != var_type; } bool check_update_type(Item_result type) { return 1; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { return (*value_ptr_func)(thd); } @@ -827,9 +826,9 @@ public: sys_var_have_option(sys_var_chain *chain, const char *variable_name): sys_var(variable_name) { chain_sys_var(chain); } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte*) show_comp_option_name[get_option()]; + return (uchar*) show_comp_option_name[get_option()]; } bool update(THD *thd, set_var *var) { return 1; } bool check_default(enum_var_type type) { return 1; } @@ -890,7 +889,7 @@ public: } bool check_default(enum_var_type type) { return 0; } bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); virtual void set_default(THD *thd, enum_var_type type); }; @@ -909,15 +908,15 @@ public: } void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_INT; } - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; class sys_var_trust_routine_creators :public sys_var_bool_ptr { /* We need a derived class only to have a warn_deprecated() */ public: - sys_var_trust_routine_creators(sys_var_chain *chain, const char *name_arg, - my_bool *value_arg) : + sys_var_trust_routine_creators(sys_var_chain *chain, + const char *name_arg, my_bool *value_arg) : sys_var_bool_ptr(chain, name_arg, value_arg) {}; void warn_deprecated(THD *thd); void set_default(THD *thd, enum_var_type type); @@ -959,7 +958,7 @@ public: } bool check_default(enum_var_type type) { return 0; } bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); virtual void set_default(THD *thd, enum_var_type type); }; @@ -971,7 +970,7 @@ public: sys_var_event_scheduler(sys_var_chain *chain, const char *name_arg) : sys_var_long_ptr(chain, name_arg, NULL, NULL) {}; bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); SHOW_TYPE show_type() { return SHOW_CHAR; } bool check(THD *thd, set_var *var); bool check_update_type(Item_result type) @@ -1114,10 +1113,10 @@ class NAMED_LIST :public ilink const char *name; uint name_length; public: - gptr data; + uchar* data; NAMED_LIST(I_List<NAMED_LIST> *links, const char *name_arg, - uint name_length_arg, gptr data_arg) + uint name_length_arg, uchar* data_arg) :name_length(name_length_arg), data(data_arg) { name= my_strndup(name_arg, name_length, MYF(MY_WME)); @@ -1129,12 +1128,12 @@ public: } ~NAMED_LIST() { - my_free((char*) name, MYF(0)); + my_free((uchar*) name, MYF(0)); } friend bool process_key_caches(int (* func) (const char *name, KEY_CACHE *)); friend void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char*, gptr)); + void (*free_element)(const char*, uchar*)); }; /* updated in sql_acl.cc */ @@ -1171,7 +1170,7 @@ extern sys_var_str sys_init_slave; extern sys_var_thd_time_zone sys_time_zone; extern sys_var_thd_bit sys_autocommit; CHARSET_INFO *get_old_charset_by_name(const char *old_name); -gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length, +uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length, NAMED_LIST **found); extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path; @@ -1182,4 +1181,4 @@ KEY_CACHE *get_or_create_key_cache(const char *name, uint length); void free_key_cache(const char *name, KEY_CACHE *key_cache); bool process_key_caches(int (* func) (const char *name, KEY_CACHE *)); void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char*, gptr)); + void (*free_element)(const char*, uchar*)); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index bb2d9c25a77..1dde977800b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5843,8 +5843,8 @@ ER_BINLOG_ROW_LOGGING_FAILED eng "Writing one row to the row-based binary log failed" ger "Schreiben einer Zeilen ins zeilenbasierte Binärlog fehlgeschlagen" ER_BINLOG_ROW_WRONG_TABLE_DEF - eng "Table definition on master and slave does not match" - ger "Tabellendefinition auf Master und Slave stimmt nicht überein" + eng "Table definition on master and slave does not match: %s" + ger "Tabellendefinition auf Master und Slave stimmt nicht überein: %s" ER_BINLOG_ROW_RBR_TO_SBR eng "Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events" ger "Slave, die mit --log-slave-updates laufen, müssen zeilenbasiertes Loggen verwenden, um zeilenbasierte Binärlog-Ereignisse loggen zu können" @@ -6059,3 +6059,20 @@ ER_SLAVE_INCIDENT eng "The incident %s occured on the master. Message: %-.64s" ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT eng "Table has no partition for some existing values" +ER_ADMIN_WRONG_MRG_TABLE + eng "Table '%-.64s' is differently defined or of non-MyISAM type or doesn't exist" +ER_BINLOG_UNSAFE_STATEMENT + eng "Statement is not safe to log in statement format." + swe "Detta är inte säkert att logga i statement-format." +ER_SLAVE_FATAL_ERROR + eng "Fatal error: %s" +ER_SLAVE_RELAY_LOG_READ_FAILURE + eng "Relay log read failure: %s" +ER_SLAVE_RELAY_LOG_WRITE_FAILURE + eng "Relay log write failure: %s" +ER_SLAVE_CREATE_EVENT_FAILURE + eng "Failed to create %s" +ER_SLAVE_MASTER_COM_FAILURE + eng "Master command %s failed: %s" +ER_BINLOG_LOGGING_IMPOSSIBLE + eng "Binary logging not possible. Message: %s" diff --git a/sql/slave.cc b/sql/slave.cc index f89a56e2087..6c7968c2b3f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -450,7 +450,7 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, #ifdef NOT_USED_YET -static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) +static int end_slave_on_walk(MASTER_INFO* mi, uchar* /*unused*/) { DBUG_ENTER("end_slave_on_walk"); @@ -529,13 +529,13 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) "it some grace period")); if (difftime(time(0), rli->last_event_start_time) > 60) { - slave_print_msg(ERROR_LEVEL, rli, 0, - "SQL thread had to stop in an unsafe situation, in " - "the middle of applying updates to a " - "non-transactional table without any primary key. " - "There is a risk of duplicate updates when the slave " - "SQL thread is restarted. Please check your tables' " - "contents after restart."); + rli->report(ERROR_LEVEL, 0, + "SQL thread had to stop in an unsafe situation, in " + "the middle of applying updates to a " + "non-transactional table without any primary key. " + "There is a risk of duplicate updates when the slave " + "SQL thread is restarted. Please check your tables' " + "contents after restart."); DBUG_RETURN(1); } } @@ -544,70 +544,6 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) /* - Writes a message to stderr, and if it's an error message, to - rli->last_slave_error and rli->last_slave_errno (which will be displayed by - SHOW SLAVE STATUS). - - SYNOPSIS - slave_print_msg() - level The severity level - rli - err_code The error code - msg The message (usually related to the error code, but can - contain more information). - ... (this is printf-like format, with % symbols in msg) - - RETURN VALUES - void -*/ - -void slave_print_msg(enum loglevel level, RELAY_LOG_INFO const *rli, - int err_code, const char* msg, ...) -{ - void (*report_function)(const char *, ...); - char buff[MAX_SLAVE_ERRMSG], *pbuff= buff; - uint pbuffsize= sizeof(buff); - va_list args; - DBUG_ENTER("slave_print_msg"); - - va_start(args,msg); - switch (level) - { - case ERROR_LEVEL: - /* - This my_error call only has effect in client threads. - Slave threads do nothing in my_error(). - */ - my_error(ER_UNKNOWN_ERROR, MYF(0), msg); - /* - It's an error, it must be reported in Last_error and Last_errno in SHOW - SLAVE STATUS. - */ - pbuff= const_cast<RELAY_LOG_INFO*>(rli)->last_slave_error; - pbuffsize= sizeof(rli->last_slave_error); - const_cast<RELAY_LOG_INFO*>(rli)->last_slave_errno = err_code; - report_function= sql_print_error; - break; - case WARNING_LEVEL: - report_function= sql_print_warning; - break; - case INFORMATION_LEVEL: - report_function= sql_print_information; - break; - default: - DBUG_ASSERT(0); // should not come here - DBUG_VOID_RETURN; // don't crash production builds, just do nothing - } - my_vsnprintf(pbuff, pbuffsize, msg, args); - /* If the msg string ends with '.', do not add a ',' it would be ugly */ - if (pbuff[0] && (*(strend(pbuff)-1) == '.')) - (*report_function)("Slave: %s Error_code: %d", pbuff, err_code); - else - (*report_function)("Slave: %s, Error_code: %d", pbuff, err_code); - DBUG_VOID_RETURN; -} - -/* skip_load_data_infile() NOTES @@ -620,7 +556,7 @@ void skip_load_data_infile(NET *net) (void)net_request_file(net, "/dev/null"); (void)my_net_read(net); // discard response - (void)net_write_command(net, 0, "", 0, "", 0); // Send ok + (void)net_write_command(net, 0, (uchar*) "", 0, (uchar*) "", 0); // ok DBUG_VOID_RETURN; } @@ -628,7 +564,8 @@ void skip_load_data_infile(NET *net) bool net_request_file(NET* net, const char* fname) { DBUG_ENTER("net_request_file"); - DBUG_RETURN(net_write_command(net, 251, fname, strlen(fname), "", 0)); + DBUG_RETURN(net_write_command(net, 251, (uchar*) fname, strlen(fname), + (uchar*) "", 0)); } /* @@ -774,7 +711,9 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) /* as we are here, we tried to allocate the event */ if (!mi->rli.relay_log.description_event_for_queue) { - sql_print_error("Slave I/O thread failed to create a default Format_description_log_event"); + mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE, + ER(ER_SLAVE_CREATE_EVENT_FAILURE), + "default Format_description_log_event"); DBUG_RETURN(1); } @@ -1137,18 +1076,21 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) { ev->server_id= 0; // don't be ignored by slave SQL thread if (unlikely(rli->relay_log.append(ev))) - sql_print_error("Slave I/O thread failed to write a Rotate event" - " to the relay log, " - "SHOW SLAVE STATUS may be inaccurate"); + mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, + ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), + "failed to write a Rotate event" + " to the relay log, SHOW SLAVE STATUS may be" + " inaccurate"); rli->relay_log.harvest_bytes_written(&rli->log_space_total); if (flush_master_info(mi, 1)) sql_print_error("Failed to flush master info file"); delete ev; } else - sql_print_error("Slave I/O thread failed to create a Rotate event" - " (out of memory?), " - "SHOW SLAVE STATUS may be inaccurate"); + mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE, + ER(ER_SLAVE_CREATE_EVENT_FAILURE), + "Rotate_event (out of memory?)," + " SHOW SLAVE STATUS may be inaccurate"); } else pthread_mutex_unlock(log_lock); @@ -1156,9 +1098,9 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) } -int register_slave_on_master(MYSQL* mysql) +int register_slave_on_master(MYSQL* mysql, MASTER_INFO *mi) { - char buf[1024], *pos= buf; + uchar buf[1024], *pos= buf; uint report_host_len, report_user_len=0, report_password_len=0; DBUG_ENTER("register_slave_on_master"); @@ -1175,20 +1117,21 @@ int register_slave_on_master(MYSQL* mysql) DBUG_RETURN(0); // safety int4store(pos, server_id); pos+= 4; - pos= net_store_data(pos, report_host, report_host_len); - pos= net_store_data(pos, report_user, report_user_len); - pos= net_store_data(pos, report_password, report_password_len); + pos= net_store_data(pos, (uchar*) report_host, report_host_len); + pos= net_store_data(pos, (uchar*) report_user, report_user_len); + pos= net_store_data(pos, (uchar*) report_password, report_password_len); int2store(pos, (uint16) report_port); pos+= 2; int4store(pos, rpl_recovery_rank); pos+= 4; /* The master will fill in master_id */ int4store(pos, 0); pos+= 4; - if (simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf, - (uint) (pos- buf), 0)) + if (simple_command(mysql, COM_REGISTER_SLAVE, buf, (size_t) (pos- buf), 0)) { - sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'", - mysql_errno(mysql), - mysql_error(mysql)); + char buf[256]; + my_snprintf(buf, sizeof(buf), + "%s (Errno: %d)", mysql_error(mysql), mysql_errno(mysql)); + mi->report(ERROR_LEVEL, ER_SLAVE_MASTER_COM_FAILURE, + ER(ER_SLAVE_MASTER_COM_FAILURE), "COM_REGISTER_SLAVE", buf); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -1258,6 +1201,10 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) MYSQL_TYPE_LONGLONG)); field_list.push_back(new Item_empty_string("Master_SSL_Verify_Server_Cert", 3)); + field_list.push_back(new Item_return_int("Last_IO_Errno", 4, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_empty_string("Last_IO_Error", 20)); + field_list.push_back(new Item_return_int("Last_SQL_Errno", 4, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_empty_string("Last_SQL_Error", 20)); if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -1306,8 +1253,8 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) rpl_filter->get_wild_ignore_table(&tmp); protocol->store(&tmp); - protocol->store(mi->rli.last_slave_errno); - protocol->store(mi->rli.last_slave_error, &my_charset_bin); + protocol->store(mi->rli.last_error().number); + protocol->store(mi->rli.last_error().message, &my_charset_bin); protocol->store((uint32) mi->rli.slave_skip_counter); protocol->store((ulonglong) mi->rli.group_master_log_pos); protocol->store((ulonglong) mi->rli.log_space_total); @@ -1368,10 +1315,19 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) } protocol->store(mi->ssl_verify_server_cert? "Yes":"No", &my_charset_bin); + // Last_IO_Errno + protocol->store(mi->last_error().number); + // Last_IO_Error + protocol->store(mi->last_error().message, &my_charset_bin); + // Last_SQL_Errno + protocol->store(mi->rli.last_error().number); + // Last_SQL_Error + protocol->store(mi->rli.last_error().message, &my_charset_bin); + pthread_mutex_unlock(&mi->rli.data_lock); pthread_mutex_unlock(&mi->data_lock); - if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) + if (my_net_write(&thd->net, (uchar*) thd->packet.ptr(), packet->length())) DBUG_RETURN(TRUE); } send_eof(thd); @@ -1499,7 +1455,7 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, static int request_dump(MYSQL* mysql, MASTER_INFO* mi, bool *suppress_warnings) { - char buf[FN_REFLEN + 10]; + uchar buf[FN_REFLEN + 10]; int len; int binlog_flags = 0; // for now char* logname = mi->master_log_name; @@ -1533,10 +1489,9 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi, static int request_table_dump(MYSQL* mysql, const char* db, const char* table) { - char buf[1024]; + uchar buf[1024], *p = buf; DBUG_ENTER("request_table_dump"); - char * p = buf; uint table_len = (uint) strlen(table); uint db_len = (uint) strlen(db); if (table_len + db_len > sizeof(buf) - 2) @@ -1825,13 +1780,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) */ if (error) { - slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR, - "It was not possible to update the positions" - " of the relay log information: the slave may" - " be in an inconsistent state." - " Stopped in %s position %s", - rli->group_relay_log_name, - llstr(rli->group_relay_log_pos, buf)); + rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR, + "It was not possible to update the positions" + " of the relay log information: the slave may" + " be in an inconsistent state." + " Stopped in %s position %s", + rli->group_relay_log_name, + llstr(rli->group_relay_log_pos, buf)); DBUG_RETURN(1); } } @@ -1910,7 +1865,8 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) DBUG_RETURN(exec_res); } pthread_mutex_unlock(&rli->data_lock); - slave_print_msg(ERROR_LEVEL, rli, 0, "\ + rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE, + ER(ER_SLAVE_RELAY_LOG_READ_FAILURE), "\ Could not parse relay log event entry. The possible reasons are: the master's \ binary log is corrupted (you can check this by running 'mysqlbinlog' on the \ binary log), the slave's relay log is corrupted (you can check this by running \ @@ -1977,7 +1933,8 @@ pthread_handler_t handle_slave_io(void *arg) if (!(mi->mysql = mysql = mysql_init(NULL))) { - sql_print_error("Slave I/O thread: error in mysql_init()"); + mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), "error in mysql_init()"); goto err; } @@ -2016,12 +1973,13 @@ connected: { /* Register ourselves with the master. - If fails, this is not fatal - we just print the error message and go - on with life. */ thd->proc_info = "Registering slave on master"; - if (register_slave_on_master(mysql) || update_slave_list(mysql, mi)) + if (register_slave_on_master(mysql, mi)) + { + sql_print_error("Slave I/O thread couldn't register on master"); goto err; + } } DBUG_PRINT("info",("Starting reading binary log from master")); @@ -2065,10 +2023,16 @@ dump"); } thd->proc_info = "Reconnecting after a failed binlog dump request"; - if (!suppress_warnings) - sql_print_error("Slave I/O thread: failed dump request, \ -reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME, - llstr(mi->master_log_pos,llbuff)); + if (!suppress_warnings) { + char buf[256]; + my_snprintf(buf, sizeof(buf), + "failed dump request, reconnecting to try again," + " log '%s' at postion %s", + IO_RPL_LOG_NAME, + llstr(mi->master_log_pos,llbuff)); + mi->report(WARNING_LEVEL, ER_SLAVE_MASTER_COM_FAILURE, + ER(ER_SLAVE_MASTER_COM_FAILURE), "COM_BINLOG_DUMP", buf); + } if (safe_reconnect(thd, mysql, mi, suppress_warnings) || io_slave_killed(thd,mi)) { @@ -2158,7 +2122,9 @@ reconnect done to recover from failed read"); if (queue_event(mi,(const char*)mysql->net.read_pos + 1, event_len)) { - sql_print_error("Slave I/O thread could not queue event from master"); + mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, + ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), + "could not queue event from master"); goto err; } if (flush_master_info(mi, 1)) @@ -2327,7 +2293,7 @@ pthread_handler_t handle_slave_sql(void *arg) now. But the master timestamp is reset by RESET SLAVE & CHANGE MASTER. */ - rli->clear_slave_error(); + rli->clear_error(); //tell the I/O thread to take relay_log_space_limit into account from now on pthread_mutex_lock(&rli->log_space_lock); @@ -2411,22 +2377,22 @@ Slave SQL thread aborted. Can't execute init_slave query"); codes and warnings and print this to the error log as to allow the user to locate the error */ - DBUG_PRINT("info", ("thd->net.last_errno=%d; rli->last_slave_errno=%d", - thd->net.last_errno, rli->last_slave_errno)); + uint32 const last_errno= rli->last_error().number; + + DBUG_PRINT("info", ("thd->net.last_errno=%d; rli->last_error.number=%d", + thd->net.last_errno, last_errno)); if (thd->net.last_errno != 0) { - if (rli->last_slave_errno == 0) + char const *const errmsg= + thd->net.last_error ? thd->net.last_error : "<no message>"; + if (last_errno == 0) { - slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno, - thd->net.last_error ? - thd->net.last_error : "<no message>"); + rli->report(ERROR_LEVEL, thd->net.last_errno, errmsg); } - else if (rli->last_slave_errno != (int) thd->net.last_errno) + else if (last_errno != thd->net.last_errno) { sql_print_error("Slave (additional info): %s Error_code: %d", - thd->net.last_error ? - thd->net.last_error : "<no message>", - thd->net.last_errno); + errmsg, thd->net.last_errno); } } @@ -2581,7 +2547,8 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) } if (unlikely(!num_bytes)) /* eof */ { - net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */ + /* 3.23 master wants it */ + net_write_command(net, 0, (uchar*) "", 0, (uchar*) "", 0); /* If we wrote Create_file_log_event, then we need to write Execute_load_log_event. If we did not write Create_file_log_event, @@ -2594,8 +2561,9 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) xev.log_pos = cev->log_pos; if (unlikely(mi->rli.relay_log.append(&xev))) { - sql_print_error("Slave I/O: error writing Exec_load event to \ -relay log"); + mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, + ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), + "error writing Exec_load event to relay log"); goto err; } mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total); @@ -2607,8 +2575,9 @@ relay log"); cev->block_len = num_bytes; if (unlikely(mi->rli.relay_log.append(cev))) { - sql_print_error("Slave I/O: error writing Create_file event to \ -relay log"); + mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, + ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), + "error writing Create_file event to relay log"); goto err; } cev_not_written=0; @@ -2621,8 +2590,9 @@ relay log"); aev.log_pos = cev->log_pos; if (unlikely(mi->rli.relay_log.append(&aev))) { - sql_print_error("Slave I/O: error writing Append_block event to \ -relay log"); + mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, + ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), + "error writing Append_block event to relay log"); goto err; } mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ; @@ -2723,7 +2693,8 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf, { if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME))))) { - sql_print_error("Slave I/O: out of memory for Load event"); + mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), "Memory allocation failed"); DBUG_RETURN(1); } memcpy(tmp_buf,buf,event_len); @@ -3178,14 +3149,12 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, { last_errno=mysql_errno(mysql); suppress_warnings= 0; - sql_print_error("Slave I/O thread: error %s to master " - "'%s@%s:%d': \ -Error: '%s' errno: %d retry-time: %d retries: %lu", - (reconnect ? "reconnecting" : "connecting"), - mi->user, mi->host, mi->port, - mysql_error(mysql), last_errno, - mi->connect_retry, - master_retry_count); + mi->report(ERROR_LEVEL, last_errno, + "error %s to master '%s@%s:%d'" + " - retry-time: %d retries: %lu", + (reconnect ? "reconnecting" : "connecting"), + mi->user, mi->host, mi->port, + mi->connect_retry, master_retry_count); } /* By default we try forever. The reason is that failure will trigger @@ -3296,7 +3265,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) *pos++='\n'; pos=longlong2str(rli->group_master_log_pos, pos, 10); *pos='\n'; - if (my_b_write(file, (byte*) buff, (ulong) (pos-buff)+1)) + if (my_b_write(file, (uchar*) buff, (size_t) (pos-buff)+1)) error=1; if (flush_io_cache(file)) error=1; @@ -3763,9 +3732,9 @@ bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id) " so slave stops; check error log on slave" " for more info", MYF(0), bug_id); // a verbose message for the error log - slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR, - "According to the master's version ('%s')," - " it is probable that master suffers from this bug:" + rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR, + "According to the master's version ('%s')," + " it is probable that master suffers from this bug:" " http://bugs.mysql.com/bug.php?id=%u" " and thus replicating the current binary log event" " may make the slave's data become different from the" diff --git a/sql/slave.h b/sql/slave.h index cb880c8125d..731728bde4f 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -94,9 +94,9 @@ class MASTER_INFO; extern ulong master_retry_count; extern MY_BITMAP slave_error_mask; extern bool use_slave_mask; -extern char* slave_load_tmpdir; -extern my_string master_info_file,relay_log_info_file; -extern my_string opt_relay_logname, opt_relaylog_index_name; +extern char *slave_load_tmpdir; +extern char *master_info_file, *relay_log_info_file; +extern char *opt_relay_logname, *opt_relaylog_index_name; extern my_bool opt_skip_slave_start, opt_reckless_slave; extern my_bool opt_log_slave_updates; extern ulonglong relay_log_space_limit; @@ -169,9 +169,6 @@ bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id); const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO const *rli, int error_code); void skip_load_data_infile(NET* net); -void slave_print_msg(enum loglevel level, RELAY_LOG_INFO const *rli, - int err_code, const char* msg, ...) - ATTRIBUTE_FORMAT(printf, 4, 5); void end_slave(); /* clean up */ void clear_until_condition(RELAY_LOG_INFO* rli); @@ -201,13 +198,13 @@ extern int disconnect_slave_event_count, abort_slave_event_count ; /* the master variables are defaults read from my.cnf or command line */ extern uint master_port, master_connect_retry, report_port; -extern my_string master_user, master_password, master_host, - master_info_file, relay_log_info_file, report_user, report_host, - report_password; +extern char * master_user, *master_password, *master_host; +extern char *master_info_file, *relay_log_info_file, *report_user; +extern char *report_host, *report_password; extern my_bool master_ssl; -extern my_string master_ssl_ca, master_ssl_capath, master_ssl_cert, - master_ssl_cipher, master_ssl_key; +extern char *master_ssl_ca, *master_ssl_capath, *master_ssl_cert; +extern char *master_ssl_cipher, *master_ssl_key; extern I_List<THD> threads; diff --git a/sql/sp.cc b/sql/sp.cc index f21186de021..a8e6c2844a2 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -147,10 +147,10 @@ static TABLE *open_proc_table_for_update(THD *thd) static int db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table) { - byte key[MAX_KEY_LENGTH]; // db, name, optional key length type + uchar key[MAX_KEY_LENGTH]; // db, name, optional key length type DBUG_ENTER("db_find_routine_aux"); - DBUG_PRINT("enter", ("type: %d name: %.*s", - type, name->m_name.length, name->m_name.str)); + DBUG_PRINT("enter", ("type: %d name: %.*s", + type, (int) name->m_name.length, name->m_name.str)); /* Create key to find row. We have to use field->store() to be able to @@ -215,7 +215,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) Open_tables_state open_tables_state_backup; DBUG_ENTER("db_find_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", - type, name->m_name.length, name->m_name.str)); + type, (int) name->m_name.length, name->m_name.str)); *sphp= 0; // In case of errors if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) @@ -384,32 +384,32 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged))) goto end; + thd->spcont= NULL; + { Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length()); - thd->m_lip= &lip; lex_start(thd); - ret= MYSQLparse(thd); - } - thd->spcont= 0; - if (ret || thd->is_fatal_error || newlex.sphead == NULL) - { - sp_head *sp= newlex.sphead; + if (parse_sql(thd, &lip) || newlex.sphead == NULL) + { + sp_head *sp= newlex.sphead; - if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) - goto end; - delete sp; - ret= SP_PARSE_ERROR; - } - else - { - if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) - goto end; - *sphp= newlex.sphead; - (*sphp)->set_definer(&definer_user_name, &definer_host_name); - (*sphp)->set_info(created, modified, &chistics, sql_mode); - (*sphp)->optimize(); + if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) + goto end; + delete sp; + ret= SP_PARSE_ERROR; + } + else + { + if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) + goto end; + *sphp= newlex.sphead; + (*sphp)->set_definer(&definer_user_name, &definer_host_name); + (*sphp)->set_info(created, modified, &chistics, sql_mode); + (*sphp)->optimize(); + } } + end: lex_end(thd->lex); thd->spcont= old_spcont; @@ -442,16 +442,36 @@ sp_returns_type(THD *thd, String &result, sp_head *sp) delete field; } -static int -db_create_routine(THD *thd, int type, sp_head *sp) + +/** + Write stored-routine object into mysql.proc. + + This operation stores attributes of the stored procedure/function into + the mysql.proc. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION). + @param sp Stored routine object to store. + + @return Error code. SP_OK is returned on success. Other SP_ constants are + used to indicate about errors. +*/ + +int +sp_create_routine(THD *thd, int type, sp_head *sp) { int ret; TABLE *table; char definer[USER_HOST_BUFF_SIZE]; - DBUG_ENTER("db_create_routine"); - DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length, + + DBUG_ENTER("sp_create_routine"); + DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length, sp->m_name.str)); + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); + /* This statement will be replicated as a statement, even when using row-based replication. The flag will be reset at the end of the @@ -568,10 +588,14 @@ db_create_routine(THD *thd, int type, sp_head *sp) log_query.append(STRING_WITH_LEN("CREATE ")); append_definer(thd, &log_query, &thd->lex->definer->user, &thd->lex->definer->host); - log_query.append(thd->lex->stmt_definition_begin, - (char *)sp->m_body_begin - - thd->lex->stmt_definition_begin + - sp->m_body.length); + + LEX_STRING stmt_definition; + stmt_definition.str= (char*) thd->lex->stmt_definition_begin; + stmt_definition.length= thd->lex->stmt_definition_end + - thd->lex->stmt_definition_begin; + trim_whitespace(thd->charset(), & stmt_definition); + + log_query.append(stmt_definition.str, stmt_definition.length); /* Such a statement can always go directly to binlog, no trans cache */ thd->binlog_query(THD::MYSQL_QUERY_TYPE, @@ -586,14 +610,32 @@ done: } -static int -db_drop_routine(THD *thd, int type, sp_name *name) +/** + Delete the record for the stored routine object from mysql.proc. + + The operation deletes the record for the stored routine specified by name + from the mysql.proc table and invalidates the stored-routine cache. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + @param name Stored routine name. + + @return Error code. SP_OK is returned on success. Other SP_ constants are + used to indicate about errors. +*/ + +int +sp_drop_routine(THD *thd, int type, sp_name *name) { TABLE *table; int ret; - DBUG_ENTER("db_drop_routine"); - DBUG_PRINT("enter", ("type: %d name: %.*s", - type, name->m_name.length, name->m_name.str)); + DBUG_ENTER("sp_drop_routine"); + DBUG_PRINT("enter", ("type: %d name: %.*s", + type, (int) name->m_name.length, name->m_name.str)); + + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); /* This statement will be replicated as a statement, even when using @@ -618,6 +660,8 @@ db_drop_routine(THD *thd, int type, sp_name *name) thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length, FALSE, FALSE); } + + sp_cache_invalidate(); } close_thread_tables(thd); @@ -625,18 +669,37 @@ db_drop_routine(THD *thd, int type, sp_name *name) } -static int -db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) +/** + Find and updated the record for the stored routine object in mysql.proc. + + The operation finds the record for the stored routine specified by name + in the mysql.proc table and updates it with new attributes. After + successful update, the cache is invalidated. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + @param name Stored routine name. + @param chistics New values of stored routine attributes to write. + + @return Error code. SP_OK is returned on success. Other SP_ constants are + used to indicate about errors. +*/ + +int +sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) { TABLE *table; int ret; - DBUG_ENTER("db_update_routine"); - DBUG_PRINT("enter", ("type: %d name: %.*s", - type, name->m_name.length, name->m_name.str)); + DBUG_ENTER("sp_update_routine"); + DBUG_PRINT("enter", ("type: %d name: %.*s", + type, (int) name->m_name.length, name->m_name.str)); + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); /* This statement will be replicated as a statement, even when using - row-based replication. The flag will be reset at the end of the + row-based replication. The flag will be reset at the end of the statement. */ thd->clear_current_stmt_binlog_row_based(); @@ -670,6 +733,8 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length, FALSE, FALSE); } + + sp_cache_invalidate(); } close_thread_tables(thd); @@ -755,13 +820,28 @@ print_field_values(THD *thd, TABLE *table, } -static int -db_show_routine_status(THD *thd, int type, const char *wild) +/** + Implement SHOW STATUS statement for stored routines. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + @param name_pattern Stored routine name pattern. + + @return Error code. SP_OK is returned on success. Other SP_ constants are + used to indicate about errors. +*/ + +int +sp_show_status_routine(THD *thd, int type, const char *name_pattern) { TABLE *table; TABLE_LIST tables; int res; - DBUG_ENTER("db_show_routine_status"); + DBUG_ENTER("sp_show_status_routine"); + + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); memset(&tables, 0, sizeof(tables)); tables.db= (char*)"mysql"; @@ -789,14 +869,14 @@ db_show_routine_status(THD *thd, int type, const char *wild) { switch (used_field->field_type) { case MYSQL_TYPE_TIMESTAMP: - field_list.push_back(item= - new Item_return_date_time(used_field->field_name, - MYSQL_TYPE_DATETIME)); + item= new Item_return_date_time(used_field->field_name, + MYSQL_TYPE_DATETIME); + field_list.push_back(item); break; default: - field_list.push_back(item=new Item_empty_string(used_field->field_name, - used_field-> - field_length)); + item= new Item_empty_string(used_field->field_name, + used_field->field_length); + field_list.push_back(item); break; } } @@ -840,13 +920,16 @@ db_show_routine_status(THD *thd, int type, const char *wild) res= (res == HA_ERR_END_OF_FILE) ? 0 : SP_INTERNAL_ERROR; goto err_case1; } - if ((res= print_field_values(thd, table, used_fields, type, wild))) - goto err_case1; - while (!table->file->index_next(table->record[0])) + + do { - if ((res= print_field_values(thd, table, used_fields, type, wild))) + res= print_field_values(thd, table, used_fields, type, name_pattern); + + if (res) goto err_case1; } + while (!table->file->index_next(table->record[0])); + res= SP_OK; } @@ -880,7 +963,7 @@ sp_drop_db_routines(THD *thd, char *db) ret= SP_OK; table->file->ha_index_init(0, 1); if (! table->file->index_read(table->record[0], - (byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr, + (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr, (key_part_map)1, HA_READ_KEY_EXACT)) { int nxtres; @@ -897,7 +980,7 @@ sp_drop_db_routines(THD *thd, char *db) break; } } while (! (nxtres= table->file->index_next_same(table->record[0], - (byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr, + (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr, key_len))); if (nxtres != HA_ERR_END_OF_FILE) ret= SP_KEY_NOT_FOUND; @@ -913,9 +996,62 @@ err: } -/***************************************************************************** - PROCEDURE -******************************************************************************/ +/** + Implement SHOW CREATE statement for stored routines. + + The operation finds the stored routine object specified by name and then + calls sp_head::show_create_routine() for the object. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + @param name Stored routine name. + + @return Error status. + @retval FALSE on success + @retval TRUE on error +*/ + +bool +sp_show_create_routine(THD *thd, int type, sp_name *name) +{ + bool err_status= TRUE; + sp_head *sp; + sp_cache **cache = type == TYPE_ENUM_PROCEDURE ? + &thd->sp_proc_cache : &thd->sp_func_cache; + + DBUG_ENTER("sp_show_create_routine"); + DBUG_PRINT("enter", ("name: %.*s", + (int) name->m_name.length, + name->m_name.str)); + + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); + + if (type == TYPE_ENUM_PROCEDURE) + { + /* + SHOW CREATE PROCEDURE may require two instances of one sp_head + object when SHOW CREATE PROCEDURE is called for the procedure that + is being executed. Basically, there is no actual recursion, so we + increase the recursion limit for this statement (kind of hack). + + SHOW CREATE FUNCTION does not require this because SHOW CREATE + statements are prohibitted within stored functions. + */ + + thd->variables.max_sp_recursion_depth++; + } + + if ((sp= sp_find_routine(thd, type, name, cache, FALSE))) + err_status= sp->show_create_routine(thd, type); + + if (type == TYPE_ENUM_PROCEDURE) + thd->variables.max_sp_recursion_depth--; + + DBUG_RETURN(err_status); +} + /* Obtain object representing stored procedure/function by its name from @@ -944,9 +1080,9 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, thd->variables.max_sp_recursion_depth : 0); DBUG_ENTER("sp_find_routine"); - DBUG_PRINT("enter", ("name: %.*s.%.*s, type: %d, cache only %d", - name->m_db.length, name->m_db.str, - name->m_name.length, name->m_name.str, + DBUG_PRINT("enter", ("name: %.*s.%.*s type: %d cache only %d", + (int) name->m_db.length, name->m_db.str, + (int) name->m_name.length, name->m_name.str, type, cache_only)); if ((sp= sp_cache_lookup(cp, name))) @@ -1109,151 +1245,6 @@ sp_routine_exists_in_table(THD *thd, int type, sp_name *name) } -int -sp_create_procedure(THD *thd, sp_head *sp) -{ - int ret; - DBUG_ENTER("sp_create_procedure"); - DBUG_PRINT("enter", ("name: %.*s", sp->m_name.length, sp->m_name.str)); - - ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp); - DBUG_RETURN(ret); -} - - -int -sp_drop_procedure(THD *thd, sp_name *name) -{ - int ret; - DBUG_ENTER("sp_drop_procedure"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name); - if (!ret) - sp_cache_invalidate(); - DBUG_RETURN(ret); -} - - -int -sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics) -{ - int ret; - DBUG_ENTER("sp_update_procedure"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics); - if (!ret) - sp_cache_invalidate(); - DBUG_RETURN(ret); -} - - -int -sp_show_create_procedure(THD *thd, sp_name *name) -{ - int ret= SP_KEY_NOT_FOUND; - sp_head *sp; - DBUG_ENTER("sp_show_create_procedure"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - /* - Increase the recursion limit for this statement. SHOW CREATE PROCEDURE - does not do actual recursion. - */ - thd->variables.max_sp_recursion_depth++; - if ((sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, - &thd->sp_proc_cache, FALSE))) - ret= sp->show_create_procedure(thd); - - thd->variables.max_sp_recursion_depth--; - DBUG_RETURN(ret); -} - - -int -sp_show_status_procedure(THD *thd, const char *wild) -{ - int ret; - DBUG_ENTER("sp_show_status_procedure"); - - ret= db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild); - DBUG_RETURN(ret); -} - - -/***************************************************************************** - FUNCTION -******************************************************************************/ - -int -sp_create_function(THD *thd, sp_head *sp) -{ - int ret; - DBUG_ENTER("sp_create_function"); - DBUG_PRINT("enter", ("name: %.*s", sp->m_name.length, sp->m_name.str)); - - ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, sp); - DBUG_RETURN(ret); -} - - -int -sp_drop_function(THD *thd, sp_name *name) -{ - int ret; - DBUG_ENTER("sp_drop_function"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name); - if (!ret) - sp_cache_invalidate(); - DBUG_RETURN(ret); -} - - -int -sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics) -{ - int ret; - DBUG_ENTER("sp_update_procedure"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics); - if (!ret) - sp_cache_invalidate(); - DBUG_RETURN(ret); -} - - -int -sp_show_create_function(THD *thd, sp_name *name) -{ - sp_head *sp; - DBUG_ENTER("sp_show_create_function"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - if ((sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, name, - &thd->sp_func_cache, FALSE))) - { - int ret= sp->show_create_function(thd); - - DBUG_RETURN(ret); - } - DBUG_RETURN(SP_KEY_NOT_FOUND); -} - - -int -sp_show_status_function(THD *thd, const char *wild) -{ - int ret; - DBUG_ENTER("sp_show_status_function"); - ret= db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild); - DBUG_RETURN(ret); -} - - /* Structure that represents element in the set of stored routines used by statement or routine. @@ -1278,11 +1269,12 @@ struct Sroutine_hash_entry }; -extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first) +extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, + my_bool first) { Sroutine_hash_entry *rn= (Sroutine_hash_entry *)ptr; *plen= rn->key.length; - return (byte *)rn->key.str; + return (uchar *)rn->key.str; } @@ -1363,7 +1355,7 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, Query_tables_list::START_SROUTINES_HASH_SIZE, 0, 0, sp_sroutine_key, 0, 0); - if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) + if (!hash_search(&lex->sroutines, (uchar *)key->str, key->length)) { Sroutine_hash_entry *rn= (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) + @@ -1373,8 +1365,8 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, rn->key.length= key->length; rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); memcpy(rn->key.str, key->str, key->length); - my_hash_insert(&lex->sroutines, (byte *)rn); - lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); + my_hash_insert(&lex->sroutines, (uchar *)rn); + lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next); rn->belong_to_view= belong_to_view; return TRUE; } @@ -1432,7 +1424,7 @@ void sp_remove_not_own_routines(LEX *lex) but we want to be more future-proof. */ next_rt= not_own_rt->next; - hash_delete(&lex->sroutines, (byte *)not_own_rt); + hash_delete(&lex->sroutines, (uchar *)not_own_rt); } *(Sroutine_hash_entry **)lex->sroutines_list_own_last= NULL; @@ -1464,8 +1456,8 @@ void sp_update_sp_used_routines(HASH *dst, HASH *src) for (uint i=0 ; i < src->records ; i++) { Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); - if (!hash_search(dst, (byte *)rt->key.str, rt->key.length)) - my_hash_insert(dst, (byte *)rt); + if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length)) + my_hash_insert(dst, (uchar *)rt); } } @@ -44,37 +44,20 @@ sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any, bool no_error); int sp_routine_exists_in_table(THD *thd, int type, sp_name *name); -int -sp_create_procedure(THD *thd, sp_head *sp); - -int -sp_drop_procedure(THD *thd, sp_name *name); - +bool +sp_show_create_routine(THD *thd, int type, sp_name *name); int -sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics); +sp_show_status_routine(THD *thd, int type, const char *wild); int -sp_show_create_procedure(THD *thd, sp_name *name); +sp_create_routine(THD *thd, int type, sp_head *sp); int -sp_show_status_procedure(THD *thd, const char *wild); +sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics); int -sp_create_function(THD *thd, sp_head *sp); - -int -sp_drop_function(THD *thd, sp_name *name); - -int -sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics); - -int -sp_show_create_function(THD *thd, sp_name *name); - -int -sp_show_status_function(THD *thd, const char *wild); - +sp_drop_routine(THD *thd, int type, sp_name *name); /* Procedures for pre-caching of stored routines and building table list @@ -93,7 +76,8 @@ int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, TABLE_LIST *table); -extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); +extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, + my_bool first); /* Routines which allow open/lock and close mysql.proc table even when diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index de4e1efd496..84b15ee15c4 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -39,12 +39,12 @@ public: inline void insert(sp_head *sp) { /* TODO: why don't we check return value? */ - my_hash_insert(&m_hashtable, (const byte *)sp); + my_hash_insert(&m_hashtable, (const uchar *)sp); } inline sp_head *lookup(char *name, uint namelen) { - return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen); + return (sp_head *)hash_search(&m_hashtable, (const uchar *)name, namelen); } #ifdef NOT_USED @@ -53,7 +53,7 @@ public: sp_head *sp= lookup(name, namelen); if (sp) { - hash_delete(&m_hashtable, (byte *)sp); + hash_delete(&m_hashtable, (uchar *)sp); return TRUE; } return FALSE; @@ -130,7 +130,7 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp) return; // End of memory error c->version= Cversion; // No need to lock when reading long variable } - DBUG_PRINT("info",("sp_cache: inserting: %.*s", sp->m_qname.length, + DBUG_PRINT("info",("sp_cache: inserting: %.*s", (int) sp->m_qname.length, sp->m_qname.str)); c->insert(sp); *cp= c; // Update *cp if it was NULL @@ -214,12 +214,12 @@ void sp_cache_flush_obsolete(sp_cache **cp) Internal functions *************************************************************************/ -static byte *hash_get_key_for_sp_head(const byte *ptr, uint *plen, - my_bool first) +static uchar *hash_get_key_for_sp_head(const uchar *ptr, size_t *plen, + my_bool first) { sp_head *sp= (sp_head *)ptr; *plen= sp->m_qname.length; - return (byte*) sp->m_qname.str; + return (uchar*) sp->m_qname.str; } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 2f78f0b24dd..821d19dca79 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -385,13 +385,13 @@ void sp_name::init_qname(THD *thd) { m_sroutines_key.length= m_db.length + m_name.length + 2; - if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1))) + if (!(m_sroutines_key.str= (char*) thd->alloc(m_sroutines_key.length + 1))) return; m_qname.length= m_sroutines_key.length - 1; m_qname.str= m_sroutines_key.str + 1; sprintf(m_qname.str, "%.*s.%.*s", - m_db.length, (m_db.length ? m_db.str : ""), - m_name.length, m_name.str); + (int) m_db.length, (m_db.length ? m_db.str : ""), + (int) m_name.length, m_name.str); } @@ -485,8 +485,7 @@ sp_head::sp_head() */ m_db= m_name= m_qname= str_reset; - extern byte * - sp_table_key(const byte *ptr, uint *plen, my_bool first); + extern uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first); DBUG_ENTER("sp_head::sp_head"); m_backpatch.empty(); @@ -565,24 +564,23 @@ sp_head::init_strings(THD *thd, LEX *lex) m_params.str= strmake_root(root, m_param_begin, m_params.length); } - /* If ptr has overrun end_of_query then end_of_query is the end */ - endp= (lip->ptr > lip->end_of_query ? lip->end_of_query : lip->ptr); - /* - Trim "garbage" at the end. This is sometimes needed with the - "/ * ! VERSION... * /" wrapper in dump files. - */ - endp= skip_rear_comments(m_body_begin, endp); + endp= lip->get_cpp_ptr(); + lex->stmt_definition_end= endp; m_body.length= endp - m_body_begin; m_body.str= strmake_root(root, m_body_begin, m_body.length); - m_defstr.length= endp - lip->buf; - m_defstr.str= strmake_root(root, lip->buf, m_defstr.length); + trim_whitespace(thd->charset(), & m_body); + + m_defstr.length= endp - lip->get_cpp_buf(); + m_defstr.str= strmake_root(root, lip->get_cpp_buf(), m_defstr.length); + trim_whitespace(thd->charset(), & m_defstr); + DBUG_VOID_RETURN; } static TYPELIB * -create_typelib(MEM_ROOT *mem_root, create_field *field_def, List<String> *src) +create_typelib(MEM_ROOT *mem_root, Create_field *field_def, List<String> *src) { TYPELIB *result= NULL; CHARSET_INFO *cs= field_def->charset; @@ -637,17 +635,10 @@ int sp_head::create(THD *thd) { DBUG_ENTER("sp_head::create"); - int ret; - DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s", m_type, m_name.str, m_params.str, m_body.str)); - if (m_type == TYPE_ENUM_FUNCTION) - ret= sp_create_function(thd, this); - else - ret= sp_create_procedure(thd, this); - - DBUG_RETURN(ret); + DBUG_RETURN(sp_create_routine(thd, m_type, this)); } sp_head::~sp_head() @@ -714,7 +705,7 @@ sp_head::create_result_field(uint field_max_length, const char *field_name, field_max_length : m_return_field_def.length; field= ::make_field(table->s, /* TABLE_SHARE ptr */ - (char*) 0, /* field ptr */ + (uchar*) 0, /* field ptr */ field_length, /* field [max] length */ (uchar*) "", /* null ptr */ 0, /* null bit */ @@ -978,7 +969,7 @@ sp_head::execute(THD *thd) String old_packet; /* Use some extra margin for possible SP recursion and functions */ - if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet)) + if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (uchar*)&old_packet)) DBUG_RETURN(TRUE); /* init per-instruction memroot */ @@ -1277,30 +1268,31 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc, #endif // ! NO_EMBEDDED_ACCESS_CHECKS -/* - Execute a trigger: - - changes security context for triggers - - switch to new memroot - - call sp_head::execute - - restore old memroot - - restores security context +/** + Execute trigger stored program. - SYNOPSIS - sp_head::execute_trigger() - thd Thread handle - db database name - table table name - grant_info GRANT_INFO structure to be filled with - information about definer's privileges - on subject table - - RETURN - FALSE on success - TRUE on error + Execute a trigger: + - changes security context for triggers; + - switch to new memroot; + - call sp_head::execute; + - restore old memroot; + - restores security context. + + @param thd Thread context. + @param db_name Database name. + @param table_name Table name. + @param grant_info GRANT_INFO structure to be filled with information + about definer's privileges on subject table. + + @return Error status. + @retval FALSE on success. + @retval TRUE on error. */ bool -sp_head::execute_trigger(THD *thd, const char *db, const char *table, +sp_head::execute_trigger(THD *thd, + const LEX_STRING *db_name, + const LEX_STRING *table_name, GRANT_INFO *grant_info) { sp_rcontext *octx = thd->spcont; @@ -1313,6 +1305,46 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table, DBUG_ENTER("sp_head::execute_trigger"); DBUG_PRINT("info", ("trigger %s", m_name.str)); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Security_context *save_ctx= NULL; + + + if (m_chistics->suid != SP_IS_NOT_SUID && + m_security_ctx.change_security_context(thd, + &m_definer_user, + &m_definer_host, + &m_db, + &save_ctx)) + DBUG_RETURN(TRUE); + + /* + Fetch information about table-level privileges for subject table into + GRANT_INFO instance. The access check itself will happen in + Item_trigger_field, where this information will be used along with + information about column-level privileges. + */ + + fill_effective_table_privileges(thd, + grant_info, + db_name->str, + table_name->str); + + /* Check that the definer has TRIGGER privilege on the subject table. */ + + if (!(grant_info->privilege & TRIGGER_ACL)) + { + char priv_desc[128]; + get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL); + + my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc, + thd->security_ctx->priv_user, thd->security_ctx->host_or_ip, + table_name->str); + + m_security_ctx.restore_security_context(thd, save_ctx); + DBUG_RETURN(TRUE); + } +#endif // NO_EMBEDDED_ACCESS_CHECKS + /* Prepare arena and memroot for objects which lifetime is whole duration of trigger call (sp_rcontext, it's tables and items, @@ -1345,11 +1377,19 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table, err_with_cleanup: thd->restore_active_arena(&call_arena, &backup_arena); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + m_security_ctx.restore_security_context(thd, save_ctx); +#endif // NO_EMBEDDED_ACCESS_CHECKS + delete nctx; call_arena.free_items(); free_root(&call_mem_root, MYF(0)); thd->spcont= octx; + if (thd->killed) + thd->send_kill_message(); + DBUG_RETURN(err_status); } @@ -1665,7 +1705,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) { List_iterator<Item> it_args(*args); - DBUG_PRINT("info",(" %.*s: eval args", m_name.length, m_name.str)); + DBUG_PRINT("info",(" %.*s: eval args", (int) m_name.length, m_name.str)); for (uint i= 0 ; i < params ; i++) { @@ -1723,7 +1763,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (!thd->in_sub_stmt) close_thread_tables(thd, 0, 0); - DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str)); + DBUG_PRINT("info",(" %.*s: eval args done", + (int) m_name.length, m_name.str)); } if (!(m_flags & LOG_SLOW_STATEMENTS) && thd->enable_slow_log) { @@ -1831,8 +1872,6 @@ sp_head::reset_lex(THD *thd) sublex->trg_table_fields.empty(); sublex->sp_lex_in_use= FALSE; - sublex->in_comment= oldlex->in_comment; - /* Reset type info. */ sublex->charset= NULL; @@ -1862,7 +1901,7 @@ sp_head::restore_lex(THD *thd) cannot switch from statement-based to row-based only for this substatement). */ - if (sublex->binlog_row_based_if_mixed) + if (sublex->is_stmt_unsafe()) m_flags|= BINLOG_ROW_BASED_IF_MIXED; /* @@ -1912,7 +1951,7 @@ sp_head::backpatch(sp_label_t *lab) } /* - Prepare an instance of create_field for field creation (fill all necessary + Prepare an instance of Create_field for field creation (fill all necessary attributes). SYNOPSIS @@ -1920,7 +1959,7 @@ sp_head::backpatch(sp_label_t *lab) thd [IN] Thread handle lex [IN] Yacc parsing context field_type [IN] Field type - field_def [OUT] An instance of create_field to be filled + field_def [OUT] An instance of Create_field to be filled RETURN FALSE on success @@ -1930,7 +1969,7 @@ sp_head::backpatch(sp_label_t *lab) bool sp_head::fill_field_definition(THD *thd, LEX *lex, enum enum_field_types field_type, - create_field *field_def) + Create_field *field_def) { HA_CREATE_INFO sp_db_info; LEX_STRING cmt = { 0, 0 }; @@ -2015,6 +2054,13 @@ sp_head::set_info(longlong created, longlong modified, void +sp_head::set_body_begin_ptr(Lex_input_stream *lip, const char *begin_ptr) +{ + m_body_begin= begin_ptr; +} + + +void sp_head::set_definer(const char *definer, uint definerlen) { char user_name_holder[USERNAME_LENGTH + 1]; @@ -2104,49 +2150,97 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) } -int -sp_head::show_create_procedure(THD *thd) +/** + Implement SHOW CREATE statement for stored routines. + + @param thd Thread context. + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + + @return Error status. + @retval FALSE on success + @retval TRUE on error +*/ + +bool +sp_head::show_create_routine(THD *thd, int type) { + const char *col1_caption= type == TYPE_ENUM_PROCEDURE ? + "Procedure" : "Function"; + + const char *col3_caption= type == TYPE_ENUM_PROCEDURE ? + "Create Procedure" : "Create Function"; + + bool err_status; + Protocol *protocol= thd->protocol; - char buff[2048]; - String buffer(buff, sizeof(buff), system_charset_info); - int res; - List<Item> field_list; + List<Item> fields; + LEX_STRING sql_mode; + bool full_access; - DBUG_ENTER("sp_head::show_create_procedure"); - DBUG_PRINT("info", ("procedure %s", m_name.str)); + + DBUG_ENTER("sp_head::show_create_routine"); + DBUG_PRINT("info", ("routine %s", m_name.str)); + + DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || + type == TYPE_ENUM_FUNCTION); if (check_show_routine_access(thd, this, &full_access)) - DBUG_RETURN(1); + DBUG_RETURN(TRUE); - sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode, - &sql_mode); - field_list.push_back(new Item_empty_string("Procedure", NAME_CHAR_LEN)); - field_list.push_back(new Item_empty_string("sql_mode", sql_mode.length)); - // 1024 is for not to confuse old clients - Item_empty_string *definition= - new Item_empty_string("Create Procedure", max(buffer.length(),1024)); - definition->maybe_null= TRUE; - field_list.push_back(definition); + sys_var_thd_sql_mode::symbolic_mode_representation( + thd, m_sql_mode, &sql_mode); + + /* Send header. */ + + fields.push_back(new Item_empty_string(col1_caption, NAME_CHAR_LEN)); + fields.push_back(new Item_empty_string("sql_mode", sql_mode.length)); + + { + /* + NOTE: SQL statement field must be not less than 1024 in order not to + confuse old clients. + */ + + Item_empty_string *stmt_fld= + new Item_empty_string(col3_caption, + max(m_defstr.length, 1024)); + + stmt_fld->maybe_null= TRUE; + + fields.push_back(stmt_fld); + } + + if (protocol->send_fields(&fields, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + { + DBUG_RETURN(TRUE); + } + + /* Send data. */ - if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | - Protocol::SEND_EOF)) - DBUG_RETURN(1); protocol->prepare_for_resend(); + protocol->store(m_name.str, m_name.length, system_charset_info); - protocol->store((char*) sql_mode.str, sql_mode.length, system_charset_info); + protocol->store(sql_mode.str, sql_mode.length, system_charset_info); + if (full_access) - protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + protocol->store(m_defstr.str, m_defstr.length, &my_charset_bin); else protocol->store_null(); - res= protocol->write(); - send_eof(thd); - DBUG_RETURN(res); + err_status= protocol->write(); + + if (!err_status) + send_eof(thd); + + DBUG_RETURN(err_status); } + + /* Add instruction to SP @@ -2166,49 +2260,7 @@ void sp_head::add_instr(sp_instr *instr) entire stored procedure, as their life span is equal. */ instr->mem_root= &main_mem_root; - insert_dynamic(&m_instr, (gptr)&instr); -} - - -int -sp_head::show_create_function(THD *thd) -{ - Protocol *protocol= thd->protocol; - char buff[2048]; - String buffer(buff, sizeof(buff), system_charset_info); - int res; - List<Item> field_list; - LEX_STRING sql_mode; - bool full_access; - DBUG_ENTER("sp_head::show_create_function"); - DBUG_PRINT("info", ("procedure %s", m_name.str)); - - if (check_show_routine_access(thd, this, &full_access)) - DBUG_RETURN(1); - - sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode, - &sql_mode); - field_list.push_back(new Item_empty_string("Function",NAME_CHAR_LEN)); - field_list.push_back(new Item_empty_string("sql_mode", sql_mode.length)); - Item_empty_string *definition= - new Item_empty_string("Create Function", max(buffer.length(),1024)); - definition->maybe_null= TRUE; - field_list.push_back(definition); - - if (protocol->send_fields(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - DBUG_RETURN(1); - protocol->prepare_for_resend(); - protocol->store(m_name.str, m_name.length, system_charset_info); - protocol->store(sql_mode.str, sql_mode.length, system_charset_info); - if (full_access) - protocol->store(m_defstr.str, m_defstr.length, system_charset_info); - else - protocol->store_null(); - res= protocol->write(); - send_eof(thd); - - DBUG_RETURN(res); + insert_dynamic(&m_instr, (uchar*)&instr); } @@ -2252,7 +2304,7 @@ void sp_head::optimize() sp_instr *ibp; List_iterator_fast<sp_instr> li(bp); - set_dynamic(&m_instr, (gptr)&i, dst); + set_dynamic(&m_instr, (uchar*)&i, dst); while ((ibp= li++)) { sp_instr_opt_meta *im= static_cast<sp_instr_opt_meta *>(ibp); @@ -3453,12 +3505,12 @@ typedef struct st_sp_table uint query_lock_count; } SP_TABLE; -byte * -sp_table_key(const byte *ptr, uint *plen, my_bool first) +uchar * +sp_table_key(const uchar *ptr, size_t *plen, my_bool first) { SP_TABLE *tab= (SP_TABLE *)ptr; *plen= tab->qname.length; - return (byte *)tab->qname.str; + return (uchar *)tab->qname.str; } @@ -3527,8 +3579,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) (and therefore should not be prelocked). Otherwise we will erroneously treat table with same name but with different alias as non-temporary. */ - if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname, tlen)) || - ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname, + if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tlen)) || + ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tlen - alen - 1)) && tab->temp)) { @@ -3558,7 +3610,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) tab->db_length= table->db_length; tab->lock_type= table->lock_type; tab->lock_count= tab->query_lock_count= 1; - my_hash_insert(&m_sptabs, (byte *)tab); + my_hash_insert(&m_sptabs, (uchar *)tab); } } return TRUE; diff --git a/sql/sp_head.h b/sql/sp_head.h index 8ebba314ec5..50f6017ca0d 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -126,7 +126,7 @@ public: int m_type; uint m_flags; // Boolean attributes of a stored routine - create_field m_return_field_def; /* This is used for FUNCTIONs only. */ + Create_field m_return_field_def; /* This is used for FUNCTIONs only. */ const char *m_tmp_query; // Temporary pointer to sub query string st_sp_chistics *m_chistics; @@ -178,8 +178,11 @@ public: // Pointers set during parsing const char *m_param_begin; const char *m_param_end; + +private: const char *m_body_begin; +public: /* Security context for stored routine which should be run under definer privileges. @@ -216,8 +219,10 @@ public: destroy(); bool - execute_trigger(THD *thd, const char *db, const char *table, - GRANT_INFO *grant_onfo); + execute_trigger(THD *thd, + const LEX_STRING *db_name, + const LEX_STRING *table_name, + GRANT_INFO *grant_info); bool execute_function(THD *thd, Item **args, uint argcount, Field *return_fld); @@ -225,11 +230,8 @@ public: bool execute_procedure(THD *thd, List<Item> *args); - int - show_create_procedure(THD *thd); - - int - show_create_function(THD *thd); + bool + show_create_routine(THD *thd, int type); void add_instr(sp_instr *instr); @@ -245,7 +247,7 @@ public: { sp_instr *i; - get_dynamic(&m_instr, (gptr)&i, m_instr.elements-1); + get_dynamic(&m_instr, (uchar*)&i, m_instr.elements-1); return i; } @@ -293,11 +295,13 @@ public: bool fill_field_definition(THD *thd, LEX *lex, enum enum_field_types field_type, - create_field *field_def); + Create_field *field_def); void set_info(longlong created, longlong modified, st_sp_chistics *chistics, ulong sql_mode); + void set_body_begin_ptr(Lex_input_stream *lip, const char *begin_ptr); + void set_definer(const char *definer, uint definerlen); void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name); @@ -327,7 +331,7 @@ public: sp_instr *ip; if (i < m_instr.elements) - get_dynamic(&m_instr, (gptr)&ip, i); + get_dynamic(&m_instr, (uchar*)&ip, i); else ip= NULL; return ip; @@ -381,7 +385,7 @@ public: the substatements not). */ if (m_flags & BINLOG_ROW_BASED_IF_MIXED) - lex->binlog_row_based_if_mixed= TRUE; + lex->set_stmt_unsafe(); } diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 780243cc79f..8babbd52ff6 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -211,7 +211,7 @@ sp_pcontext::find_variable(LEX_STRING *name, my_bool scoped) { sp_variable_t *p; - get_dynamic(&m_vars, (gptr)&p, i); + get_dynamic(&m_vars, (uchar*)&p, i); if (my_strnncoll(system_charset_info, (const uchar *)name->str, name->length, (const uchar *)p->name.str, p->name.length) == 0) @@ -238,7 +238,7 @@ sp_pcontext::find_variable(uint offset) { // This frame sp_variable_t *p; - get_dynamic(&m_vars, (gptr)&p, offset - m_var_offset); + get_dynamic(&m_vars, (uchar*)&p, offset - m_var_offset); return p; } if (m_parent) @@ -263,7 +263,7 @@ sp_pcontext::push_variable(LEX_STRING *name, enum enum_field_types type, p->mode= mode; p->offset= current_var_count(); p->dflt= NULL; - insert_dynamic(&m_vars, (gptr)&p); + insert_dynamic(&m_vars, (uchar*)&p); return p; } @@ -318,7 +318,7 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val) p->name.str= name->str; p->name.length= name->length; p->val= val; - insert_dynamic(&m_conds, (gptr)&p); + insert_dynamic(&m_conds, (uchar*)&p); } } @@ -334,7 +334,7 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped) { sp_cond_t *p; - get_dynamic(&m_conds, (gptr)&p, i); + get_dynamic(&m_conds, (uchar*)&p, i); if (my_strnncoll(system_charset_info, (const uchar *)name->str, name->length, (const uchar *)p->name.str, p->name.length) == 0) @@ -361,7 +361,7 @@ sp_pcontext::find_handler(sp_cond_type_t *cond) { sp_cond_type_t *p; - get_dynamic(&m_handlers, (gptr)&p, i); + get_dynamic(&m_handlers, (uchar*)&p, i); if (cond->type == p->type) { switch (p->type) @@ -391,7 +391,7 @@ sp_pcontext::push_cursor(LEX_STRING *name) m_max_cursor_index+= 1; n.str= name->str; n.length= name->length; - insert_dynamic(&m_cursors, (gptr)&n); + insert_dynamic(&m_cursors, (uchar*)&n); } /* @@ -406,7 +406,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) { LEX_STRING n; - get_dynamic(&m_cursors, (gptr)&n, i); + get_dynamic(&m_cursors, (uchar*)&n, i); if (my_strnncoll(system_charset_info, (const uchar *)name->str, name->length, (const uchar *)n.str, n.length) == 0) @@ -422,14 +422,14 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) void -sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst) +sp_pcontext::retrieve_field_definitions(List<Create_field> *field_def_lst) { /* Put local/context fields in the result list. */ for (uint i = 0; i < m_vars.elements; ++i) { sp_variable_t *var_def; - get_dynamic(&m_vars, (gptr) &var_def, i); + get_dynamic(&m_vars, (uchar*) &var_def, i); field_def_lst->push_back(&var_def->field_def); } @@ -453,7 +453,7 @@ sp_pcontext::find_cursor(uint offset, LEX_STRING *n) if (m_cursor_offset <= offset && offset < m_cursor_offset + m_cursors.elements) { // This frame - get_dynamic(&m_cursors, (gptr)n, offset - m_cursor_offset); + get_dynamic(&m_cursors, (uchar*)n, offset - m_cursor_offset); return TRUE; } if (m_parent) diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 5bffda79f98..aefc501b3b0 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -43,7 +43,7 @@ typedef struct sp_variable uint offset; Item *dflt; - create_field field_def; + Create_field field_def; } sp_variable_t; @@ -234,7 +234,7 @@ public: children. */ void - retrieve_field_definitions(List<create_field> *field_def_lst); + retrieve_field_definitions(List<Create_field> *field_def_lst); // Find by name sp_variable_t * @@ -273,7 +273,7 @@ public: inline bool push_case_expr_id(int case_expr_id) { - return insert_dynamic(&m_case_expr_id_lst, (gptr) &case_expr_id); + return insert_dynamic(&m_case_expr_id_lst, (uchar*) &case_expr_id); } inline void @@ -287,7 +287,7 @@ public: { int case_expr_id; - get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (gptr) &case_expr_id, + get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (uchar*) &case_expr_id, m_case_expr_id_lst.elements - 1); return case_expr_id; @@ -343,7 +343,7 @@ public: inline void push_handler(sp_cond_type_t *cond) { - insert_dynamic(&m_handlers, (gptr)&cond); + insert_dynamic(&m_handlers, (uchar*)&cond); } bool diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index e49c4eb1240..b94c733cb0a 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -102,7 +102,7 @@ bool sp_rcontext::init(THD *thd) bool sp_rcontext::init_var_table(THD *thd) { - List<create_field> field_def_lst; + List<Create_field> field_def_lst; if (!m_root_parsing_ctx->max_var_index()) return FALSE; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ba1ec66fb02..dfdd6f5c5b4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -160,11 +160,11 @@ public: }; -static byte* acl_entry_get_key(acl_entry *entry,uint *length, - my_bool not_used __attribute__((unused))) +static uchar* acl_entry_get_key(acl_entry *entry, size_t *length, + my_bool not_used __attribute__((unused))) { *length=(uint) entry->length; - return (byte*) entry->key; + return (uchar*) entry->key; } #define IP_ADDR_STRLEN (3+1+3+1+3+1+3) @@ -362,9 +362,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) host.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL; } #endif - VOID(push_dynamic(&acl_hosts,(gptr) &host)); + VOID(push_dynamic(&acl_hosts,(uchar*) &host)); } - qsort((gptr) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, + qsort((uchar*) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, sizeof(ACL_HOST),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_hosts); @@ -546,13 +546,13 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) user.access|= SUPER_ACL | EXECUTE_ACL; #endif } - VOID(push_dynamic(&acl_users,(gptr) &user)); + VOID(push_dynamic(&acl_users,(uchar*) &user)); if (!user.host.hostname || (user.host.hostname[0] == wild_many && !user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect } } - qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, sizeof(ACL_USER),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_users); @@ -609,9 +609,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) db.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; } #endif - VOID(push_dynamic(&acl_dbs,(gptr) &db)); + VOID(push_dynamic(&acl_dbs,(uchar*) &db)); } - qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, sizeof(ACL_DB),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_dbs); @@ -1110,14 +1110,15 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, */ for (i=0 ; i < acl_users.elements ; i++) { - acl_user= dynamic_element(&acl_users,i,ACL_USER*); - if ((!acl_user->user && !user[0]) || - (acl_user->user && strcmp(user, acl_user->user) == 0)) + ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*); + if ((!acl_user_tmp->user && !user[0]) || + (acl_user_tmp->user && strcmp(user, acl_user_tmp->user) == 0)) { - if (compare_hostname(&acl_user->host, host, ip)) + if (compare_hostname(&acl_user_tmp->host, host, ip)) { - res= 0; - break; + acl_user= acl_user_tmp; + res= 0; + break; } } } @@ -1152,11 +1153,11 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, DBUG_RETURN(res); } -static byte* check_get_key(ACL_USER *buff,uint *length, - my_bool not_used __attribute__((unused))) +static uchar* check_get_key(ACL_USER *buff, size_t *length, + my_bool not_used __attribute__((unused))) { *length=buff->hostname_length; - return (byte*) buff->host.hostname; + return (uchar*) buff->host.hostname; } @@ -1237,11 +1238,11 @@ static void acl_insert_user(const char *user, const char *host, set_user_salt(&acl_user, password, password_len); - VOID(push_dynamic(&acl_users,(gptr) &acl_user)); + VOID(push_dynamic(&acl_users,(uchar*) &acl_user)); if (!acl_user.host.hostname || (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect /* purecov: tested */ - qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, sizeof(ACL_USER),(qsort_cmp) acl_compare); /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ @@ -1303,8 +1304,8 @@ static void acl_insert_db(const char *user, const char *host, const char *db, acl_db.db=strdup_root(&mem,db); acl_db.access=privileges; acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); - VOID(push_dynamic(&acl_dbs,(gptr) &acl_db)); - qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + VOID(push_dynamic(&acl_dbs,(uchar*) &acl_db)); + qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, sizeof(ACL_DB),(qsort_cmp) acl_compare); } @@ -1321,7 +1322,8 @@ ulong acl_get(const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern) { ulong host_access= ~(ulong)0, db_access= 0; - uint i,key_length; + uint i; + size_t key_length; char key[ACL_KEY_LENGTH],*tmp_db,*end; acl_entry *entry; DBUG_ENTER("acl_get"); @@ -1333,8 +1335,9 @@ ulong acl_get(const char *host, const char *ip, my_casedn_str(files_charset_info, tmp_db); db=tmp_db; } - key_length=(uint) (end-key); - if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search(key,key_length))) + key_length= (size_t) (end-key); + if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key, + key_length))) { db_access=entry->access; VOID(pthread_mutex_unlock(&acl_cache->lock)); @@ -1388,7 +1391,7 @@ exit: { entry->access=(db_access & host_access); entry->length=key_length; - memcpy((gptr) entry->key,key,key_length); + memcpy((uchar*) entry->key,key,key_length); acl_cache->add(entry); } VOID(pthread_mutex_unlock(&acl_cache->lock)); @@ -1430,12 +1433,12 @@ static void init_check_host(void) break; // already stored } if (j == acl_wild_hosts.elements) // If new - (void) push_dynamic(&acl_wild_hosts,(char*) &acl_user->host); + (void) push_dynamic(&acl_wild_hosts,(uchar*) &acl_user->host); } - else if (!hash_search(&acl_check_hosts,(byte*) acl_user->host.hostname, - (uint) strlen(acl_user->host.hostname))) + else if (!hash_search(&acl_check_hosts,(uchar*) acl_user->host.hostname, + strlen(acl_user->host.hostname))) { - if (my_hash_insert(&acl_check_hosts,(byte*) acl_user)) + if (my_hash_insert(&acl_check_hosts,(uchar*) acl_user)) { // End of memory allow_all_hosts=1; // Should never happen DBUG_VOID_RETURN; @@ -1473,8 +1476,8 @@ bool acl_check_host(const char *host, const char *ip) return 0; VOID(pthread_mutex_lock(&acl_cache->lock)); - if (host && hash_search(&acl_check_hosts,(byte*) host,(uint) strlen(host)) || - ip && hash_search(&acl_check_hosts,(byte*) ip,(uint) strlen(ip))) + if (host && hash_search(&acl_check_hosts,(uchar*) host,strlen(host)) || + ip && hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip))) { VOID(pthread_mutex_unlock(&acl_cache->lock)); return 0; // Found host @@ -1533,7 +1536,7 @@ bool check_change_password(THD *thd, const char *host, const char *user, MYF(0)); return(1); } - uint len=strlen(new_password); + size_t len= strlen(new_password); if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH && len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) { @@ -1567,7 +1570,7 @@ bool change_password(THD *thd, const char *host, const char *user, /* Buffer should be extended when password length is extended. */ char buff[512]; ulong query_length; - uint new_password_len= strlen(new_password); + uint new_password_len= (uint) strlen(new_password); bool result= 1; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", @@ -1768,8 +1771,8 @@ bool hostname_requires_resolving(const char *hostname) char cur; if (!hostname) return FALSE; - int namelen= strlen(hostname); - int lhlen= strlen(my_localhost); + size_t namelen= strlen(hostname); + size_t lhlen= strlen(my_localhost); if ((namelen == lhlen) && !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, (const uchar *)my_localhost, strlen(my_localhost))) @@ -1809,11 +1812,11 @@ static bool update_user_table(THD *thd, TABLE *table, table->use_all_columns(); table->field[0]->store(host,(uint) strlen(host), system_charset_info); table->field[1]->store(user,(uint) strlen(user), system_charset_info); - key_copy((byte *) user_key, table->record[0], table->key_info, + key_copy((uchar *) user_key, table->record[0], table->key_info, table->key_info->key_length); if (table->file->index_read_idx(table->record[0], 0, - (byte *) user_key, HA_WHOLE_KEY, + (uchar *) user_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), @@ -1878,7 +1881,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, const char *password= ""; uint password_len= 0; char what= (revoke_grant) ? 'N' : 'Y'; - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; LEX *lex= thd->lex; DBUG_ENTER("replace_user_table"); @@ -2096,7 +2099,7 @@ static int replace_db_table(TABLE *table, const char *db, bool old_row_exists=0; int error; char what= (revoke_grant) ? 'N' : 'Y'; - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_db_table"); if (!initialized) @@ -2198,16 +2201,16 @@ public: uint key_length; GRANT_COLUMN(String &c, ulong y) :rights (y) { - column= memdup_root(&memex,c.ptr(), key_length=c.length()); + column= (char*) memdup_root(&memex,c.ptr(), key_length=c.length()); } }; -static byte* get_key_column(GRANT_COLUMN *buff,uint *length, +static uchar* get_key_column(GRANT_COLUMN *buff, size_t *length, my_bool not_used __attribute__((unused))) { *length=buff->key_length; - return (byte*) buff->column; + return (uchar*) buff->column; } @@ -2218,7 +2221,7 @@ public: char *db, *user, *tname, *hash_key; ulong privs; ulong sort; - uint key_length; + size_t key_length; GRANT_NAME(const char *h, const char *d,const char *u, const char *t, ulong p); GRANT_NAME (TABLE *form); @@ -2257,8 +2260,8 @@ GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, my_casedn_str(files_charset_info, db); my_casedn_str(files_charset_info, tname); } - key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; - hash_key = (char*) alloc_root(&memex,key_length); + key_length= strlen(d) + strlen(u)+ strlen(t)+3; + hash_key= (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); } @@ -2292,9 +2295,8 @@ GRANT_NAME::GRANT_NAME(TABLE *form) my_casedn_str(files_charset_info, db); my_casedn_str(files_charset_info, tname); } - key_length = ((uint) strlen(db) + (uint) strlen(user) + - (uint) strlen(tname) + 3); - hash_key = (char*) alloc_root(&memex,key_length); + key_length= (strlen(db) + strlen(user) + strlen(tname) + 3); + hash_key= (char*) alloc_root(&memex, key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); privs = (ulong) form->field[6]->val_int(); privs = fix_rights_for_table(privs); @@ -2304,7 +2306,7 @@ GRANT_NAME::GRANT_NAME(TABLE *form) GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) :GRANT_NAME(form) { - byte key[MAX_KEY_LENGTH]; + uchar key[MAX_KEY_LENGTH]; if (!db || !tname) { @@ -2338,7 +2340,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) col_privs->field[4]->store("",0, &my_charset_latin1); col_privs->file->ha_index_init(0, 1); - if (col_privs->file->index_read(col_privs->record[0], (byte*) key, + if (col_privs->file->index_read(col_privs->record[0], (uchar*) key, (key_part_map)15, HA_READ_KEY_EXACT)) { cols = 0; /* purecov: deadcode */ @@ -2359,7 +2361,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) privs = cols = 0; /* purecov: deadcode */ return; /* purecov: deadcode */ } - my_hash_insert(&hash_columns, (byte *) mem_check); + my_hash_insert(&hash_columns, (uchar *) mem_check); } while (!col_privs->file->index_next(col_privs->record[0]) && !key_cmp_if_same(col_privs,key,0,key_prefix_len)); col_privs->file->ha_index_end(); @@ -2373,11 +2375,11 @@ GRANT_TABLE::~GRANT_TABLE() } -static byte* get_grant_table(GRANT_NAME *buff,uint *length, +static uchar* get_grant_table(GRANT_NAME *buff, size_t *length, my_bool not_used __attribute__((unused))) { *length=buff->key_length; - return (byte*) buff->hash_key; + return (uchar*) buff->hash_key; } @@ -2401,10 +2403,10 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, HASH_SEARCH_STATE state; len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; - for (grant_name= (GRANT_NAME*) hash_first(name_hash, (byte*) helping, + for (grant_name= (GRANT_NAME*) hash_first(name_hash, (uchar*) helping, len, &state); grant_name ; - grant_name= (GRANT_NAME*) hash_next(name_hash,(byte*) helping, + grant_name= (GRANT_NAME*) hash_next(name_hash,(uchar*) helping, len, &state)) { if (exact) @@ -2449,7 +2451,7 @@ table_hash_search(const char *host, const char *ip, const char *db, inline GRANT_COLUMN * column_hash_search(GRANT_TABLE *t, const char *cname, uint length) { - return (GRANT_COLUMN*) hash_search(&t->hash_columns, (byte*) cname,length); + return (GRANT_COLUMN*) hash_search(&t->hash_columns, (uchar*) cname,length); } @@ -2460,7 +2462,7 @@ static int replace_column_table(GRANT_TABLE *g_t, ulong rights, bool revoke_grant) { int error=0,result=0; - byte key[MAX_KEY_LENGTH]; + uchar key[MAX_KEY_LENGTH]; uint key_prefix_length; KEY_PART_INFO *key_part= table->key_info->key_part; DBUG_ENTER("replace_column_table"); @@ -2491,7 +2493,7 @@ static int replace_column_table(GRANT_TABLE *g_t, { ulong privileges= column->rights; bool old_row_exists=0; - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; key_restore(table->record[0],key,table->key_info, key_prefix_length); @@ -2562,7 +2564,7 @@ static int replace_column_table(GRANT_TABLE *g_t, goto end; /* purecov: inspected */ } grant_column= new GRANT_COLUMN(column->column,privileges); - my_hash_insert(&g_t->hash_columns,(byte*) grant_column); + my_hash_insert(&g_t->hash_columns,(uchar*) grant_column); } } @@ -2573,7 +2575,7 @@ static int replace_column_table(GRANT_TABLE *g_t, if (revoke_grant) { - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; key_copy(user_key, table->record[0], table->key_info, key_prefix_length); @@ -2625,7 +2627,7 @@ static int replace_column_table(GRANT_TABLE *g_t, goto end; /* purecov: deadcode */ } if (grant_column) - hash_delete(&g_t->hash_columns,(byte*) grant_column); + hash_delete(&g_t->hash_columns,(uchar*) grant_column); } } } while (!table->file->index_next(table->record[0]) && @@ -2648,7 +2650,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, int old_row_exists = 1; int error=0; ulong store_table_rights, store_col_rights; - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); strxmov(grantor, thd->security_ctx->user, "@", @@ -2748,7 +2750,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } else { - hash_delete(&column_priv_hash,(byte*) grant_table); + hash_delete(&column_priv_hash,(uchar*) grant_table); } DBUG_RETURN(0); @@ -2802,7 +2804,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, store_record(table,record[1]); // store at pos 1 if (table->file->index_read_idx(table->record[0], 0, - (byte*) table->field[0]->ptr, HA_WHOLE_KEY, + (uchar*) table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { /* @@ -2865,7 +2867,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, } else { - hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name); + hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name); } DBUG_RETURN(0); @@ -3081,7 +3083,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, result= TRUE; /* purecov: deadcode */ continue; /* purecov: deadcode */ } - my_hash_insert(&column_priv_hash,(byte*) grant_table); + my_hash_insert(&column_priv_hash,(uchar*) grant_table); } /* If revoke_grant, calculate the new column privilege for tables_priv */ @@ -3136,7 +3138,6 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, } } } - grant_option=TRUE; thd->mem_root= old_root; pthread_mutex_unlock(&acl_cache->lock); @@ -3300,7 +3301,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, result= TRUE; continue; } - my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name); + my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name); } if (replace_routine_table(thd, grant_name, tables[1].table, *Str, @@ -3310,7 +3311,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, continue; } } - grant_option=TRUE; thd->mem_root= old_root; pthread_mutex_unlock(&acl_cache->lock); if (!result && !no_error) @@ -3458,7 +3458,6 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, void grant_free(void) { DBUG_ENTER("grant_free"); - grant_option = FALSE; hash_free(&column_priv_hash); hash_free(&proc_priv_hash); hash_free(&func_priv_hash); @@ -3522,7 +3521,6 @@ static my_bool grant_load(TABLE_LIST *tables) THR_MALLOC); DBUG_ENTER("grant_load"); - grant_option = FALSE; (void) hash_init(&column_priv_hash,system_charset_info, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); @@ -3552,7 +3550,6 @@ static my_bool grant_load(TABLE_LIST *tables) if (!(mem_check=new (memex_ptr) GRANT_TABLE(t_table,c_table))) { /* This could only happen if we are out memory */ - grant_option= FALSE; goto end_unlock; } @@ -3572,10 +3569,9 @@ static my_bool grant_load(TABLE_LIST *tables) if (! mem_check->ok()) delete mem_check; - else if (my_hash_insert(&column_priv_hash,(byte*) mem_check)) + else if (my_hash_insert(&column_priv_hash,(uchar*) mem_check)) { delete mem_check; - grant_option= FALSE; goto end_unlock; } } @@ -3592,7 +3588,6 @@ static my_bool grant_load(TABLE_LIST *tables) if (!(mem_check=new (&memex) GRANT_NAME(p_table))) { /* This could only happen if we are out memory */ - grant_option= FALSE; goto end_unlock; } @@ -3628,16 +3623,14 @@ static my_bool grant_load(TABLE_LIST *tables) mem_check->privs= fix_rights_for_procedure(mem_check->privs); if (! mem_check->ok()) delete mem_check; - else if (my_hash_insert(hash, (byte*) mem_check)) + else if (my_hash_insert(hash, (uchar*) mem_check)) { delete mem_check; - grant_option= FALSE; goto end_unlock; } } while (!p_table->file->index_next(p_table->record[0])); } - grant_option= TRUE; return_val=0; // Return ok end_unlock: @@ -3670,7 +3663,6 @@ my_bool grant_reload(THD *thd) { TABLE_LIST tables[3]; HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash; - bool old_grant_option; MEM_ROOT old_mem; my_bool return_val= 1; DBUG_ENTER("grant_reload"); @@ -3700,7 +3692,6 @@ my_bool grant_reload(THD *thd) old_column_priv_hash= column_priv_hash; old_proc_priv_hash= proc_priv_hash; old_func_priv_hash= func_priv_hash; - old_grant_option= grant_option; old_mem= memex; if ((return_val= grant_load(tables))) @@ -3710,7 +3701,6 @@ my_bool grant_reload(THD *thd) column_priv_hash= old_column_priv_hash; /* purecov: deadcode */ proc_priv_hash= old_proc_priv_hash; func_priv_hash= old_func_priv_hash; - grant_option= old_grant_option; /* purecov: deadcode */ memex= old_mem; /* purecov: deadcode */ } else @@ -4007,8 +3997,6 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, want_access &= ~grant->privilege; if (!want_access) return 0; // Already checked - if (!grant_option) - goto err2; rw_rdlock(&LOCK_grant); @@ -4039,7 +4027,6 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, err: rw_unlock(&LOCK_grant); -err2: char command[128]; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), @@ -4198,18 +4185,15 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, bool is_proc) { bool no_routine_acl= 1; - if (grant_option) - { - GRANT_NAME *grant_proc; - Security_context *sctx= thd->security_ctx; - rw_rdlock(&LOCK_grant); - if ((grant_proc= routine_hash_search(sctx->priv_host, - sctx->ip, db, - sctx->priv_user, - name, is_proc, 0))) - no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); - rw_unlock(&LOCK_grant); - } + GRANT_NAME *grant_proc; + Security_context *sctx= thd->security_ctx; + rw_rdlock(&LOCK_grant); + if ((grant_proc= routine_hash_search(sctx->priv_host, + sctx->ip, db, + sctx->priv_user, + name, is_proc, 0))) + no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); + rw_unlock(&LOCK_grant); return no_routine_acl; } @@ -5002,7 +4986,7 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, char *user_str= user_from->user.str; const char *host; const char *user; - byte user_key[MAX_KEY_LENGTH]; + uchar user_key[MAX_KEY_LENGTH]; uint key_prefix_length; DBUG_ENTER("handle_grant_table"); @@ -5239,11 +5223,11 @@ static int handle_grant_struct(uint struct_no, bool drop, break; case 2: - hash_delete(&column_priv_hash, (byte*) grant_name); + hash_delete(&column_priv_hash, (uchar*) grant_name); break; case 3: - hash_delete(&proc_priv_hash, (byte*) grant_name); + hash_delete(&proc_priv_hash, (uchar*) grant_name); break; } elements--; @@ -5555,6 +5539,12 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); + if (result) + my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); + + DBUG_PRINT("info", ("thd->net.last_errno: %d", thd->net.last_errno)); + DBUG_PRINT("info", ("thd->net.last_error: %s", thd->net.last_error)); + if (mysql_bin_log.is_open()) { thd->binlog_query(THD::MYSQL_QUERY_TYPE, @@ -5563,8 +5553,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); - if (result) - my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); DBUG_RETURN(result); } @@ -6081,15 +6069,15 @@ void update_schema_privilege(TABLE *table, char *buff, const char* db, int i= 2; CHARSET_INFO *cs= system_charset_info; restore_record(table, s->default_values); - table->field[0]->store(buff, strlen(buff), cs); + table->field[0]->store(buff, (uint) strlen(buff), cs); if (db) - table->field[i++]->store(db, strlen(db), cs); + table->field[i++]->store(db, (uint) strlen(db), cs); if (t_name) - table->field[i++]->store(t_name, strlen(t_name), cs); + table->field[i++]->store(t_name, (uint) strlen(t_name), cs); if (column) table->field[i++]->store(column, col_length, cs); table->field[i++]->store(priv, priv_length, cs); - table->field[i]->store(is_grantable, strlen(is_grantable), cs); + table->field[i]->store(is_grantable, (uint) strlen(is_grantable), cs); table->file->ha_write_row(table->record[0]); } @@ -6403,12 +6391,6 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, /* db privileges */ grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); - if (!grant_option) - { - DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); - DBUG_VOID_RETURN; - } - /* table privileges */ rw_rdlock(&LOCK_grant); if (grant->version != grant_version) diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index e7decf4a8fc..6b4aaa26236 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -498,7 +498,7 @@ void field_decimal::add() if (room_in_tree) { - char buf[DECIMAL_MAX_FIELD_SIZE]; + uchar buf[DECIMAL_MAX_FIELD_SIZE]; my_decimal2binary(E_DEC_FATAL_ERROR, dec, buf, item->max_length, item->decimals); if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg))) @@ -1108,7 +1108,7 @@ int collect_real(double *element, element_count count __attribute__((unused)), } // collect_real -int collect_decimal(char *element, element_count count, +int collect_decimal(uchar *element, element_count count, TREE_INFO *info) { char buff[DECIMAL_MAX_STR_LENGTH]; diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h index ac671b85e1e..ae5d88bf93e 100644 --- a/sql/sql_analyse.h +++ b/sql/sql_analyse.h @@ -143,7 +143,7 @@ public: }; -int collect_decimal(char *element, element_count count, +int collect_decimal(uchar *element, element_count count, TREE_INFO *info); class field_decimal :public field_info @@ -165,7 +165,7 @@ public: String *get_min_arg(String *); String *get_max_arg(String *); String *avg(String *s, ha_rows rows); - friend int collect_decimal(char *element, element_count count, + friend int collect_decimal(uchar *element, element_count count, TREE_INFO *info); tree_walk_action collect_enum() { return (tree_walk_action) collect_decimal; } diff --git a/sql/sql_array.h b/sql/sql_array.h index e2e12bee241..ab6fdd0c5c0 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -45,7 +45,7 @@ public: bool append(Elem &el) { - return (insert_dynamic(&array, (gptr)&el)); + return (insert_dynamic(&array, (uchar*)&el)); } int elements() diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 14edd460bc4..48c876d6d89 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -28,6 +28,8 @@ #include <io.h> #endif +#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") + /** This internal handler is used to trap internally errors that can occur when executing open table @@ -99,24 +101,23 @@ static bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, TABLE_LIST *table_desc, MEM_ROOT *mem_root); static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, bool send_refresh); -static bool reopen_table(TABLE *table); static bool has_two_write_locked_tables_with_auto_increment(TABLE_LIST *tables); -extern "C" byte *table_cache_key(const byte *record,uint *length, +extern "C" uchar *table_cache_key(const uchar *record, size_t *length, my_bool not_used __attribute__((unused))) { TABLE *entry=(TABLE*) record; *length= entry->s->table_cache_key.length; - return (byte*) entry->s->table_cache_key.str; + return (uchar*) entry->s->table_cache_key.str; } bool table_cache_init(void) { return hash_init(&open_cache, &my_charset_bin, table_cache_size+16, - 0, 0,table_cache_key, + 0, 0, table_cache_key, (hash_free_key) free_cache_entry, 0) != 0; } @@ -243,12 +244,12 @@ uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list, Functions to handle table definition cach (TABLE_SHARE) *****************************************************************************/ -extern "C" byte *table_def_key(const byte *record, uint *length, +extern "C" uchar *table_def_key(const uchar *record, size_t *length, my_bool not_used __attribute__((unused))) { TABLE_SHARE *entry=(TABLE_SHARE*) record; *length= entry->table_cache_key.length; - return (byte*) entry->table_cache_key.str; + return (uchar*) entry->table_cache_key.str; } @@ -334,7 +335,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, *error= 0; /* Read table definition from cache */ - if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(byte*) key, + if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, key_length))) goto found; @@ -351,7 +352,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, pthread_mutex_unlock(&LOCK_open); pthread_mutex_lock(&LOCK_open); /* Check that another thread didn't insert the same table in between */ - if ((old_share= hash_search(&table_def_cache, (byte*) key, key_length))) + if ((old_share= hash_search(&table_def_cache, (uchar*) key, key_length))) { (void) pthread_mutex_lock(&share->mutex); free_table_share(share); @@ -381,7 +382,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, */ assign_new_table_id(share); - if (my_hash_insert(&table_def_cache, (byte*) share)) + if (my_hash_insert(&table_def_cache, (uchar*) share)) { #ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3 pthread_mutex_unlock(&LOCK_open); @@ -407,7 +408,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, (void) pthread_mutex_lock(&share->mutex); #endif *error= share->error; - (void) hash_delete(&table_def_cache, (byte*) share); + (void) hash_delete(&table_def_cache, (uchar*) share); DBUG_RETURN(0); } share->ref_count++; // Mark in use @@ -462,7 +463,7 @@ found: oldest_unused_share->next) { pthread_mutex_lock(&oldest_unused_share->mutex); - VOID(hash_delete(&table_def_cache, (byte*) oldest_unused_share)); + VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); } DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u", @@ -585,7 +586,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) if (to_be_deleted) { DBUG_PRINT("info", ("Deleting share")); - hash_delete(&table_def_cache, (byte*) share); + hash_delete(&table_def_cache, (uchar*) share); DBUG_VOID_RETURN; } pthread_mutex_unlock(&share->mutex); @@ -611,13 +612,13 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) This code is execured when someone does FLUSH TABLES while on has locked tables. */ - (void) hash_search(&def_cache,(byte*) key,key_length); - hash_replace(&def_cache, def_cache.current_record,(byte*) name_lock); + (void) hash_search(&def_cache,(uchar*) key,key_length); + hash_replace(&def_cache, def_cache.current_record,(uchar*) name_lock); } else { /* Remove table definition */ - hash_delete(&def_cache,(byte*) share); + hash_delete(&def_cache,(uchar*) share); } pthread_mutex_unlock(&LOCK_open); free_table_share(share); @@ -662,7 +663,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) table_list.db= (char*) db; table_list.table_name= (char*) table_name; key_length= create_table_def_key((THD*) 0, key, &table_list, 0); - return (TABLE_SHARE*) hash_search(&table_def_cache,(byte*) key, key_length); + return (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, key_length); } @@ -681,7 +682,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) */ -static void close_handle_and_leave_table_as_lock(TABLE *table) +void close_handle_and_leave_table_as_lock(TABLE *table) { TABLE_SHARE *share, *old_share= table->s; char *key_buff; @@ -842,7 +843,7 @@ static void free_cache_entry(TABLE *table) } check_unused(); // consisty check } - my_free((gptr) table,MYF(0)); + my_free((uchar*) table,MYF(0)); DBUG_VOID_RETURN; } @@ -854,7 +855,7 @@ void free_io_cache(TABLE *table) if (table->sort.io_cache) { close_cached_file(table->sort.io_cache); - my_free((gptr) table->sort.io_cache,MYF(0)); + my_free((uchar*) table->sort.io_cache,MYF(0)); table->sort.io_cache=0; } DBUG_VOID_RETURN; @@ -883,17 +884,17 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, while (unused_tables) { #ifdef EXTRA_DEBUG - if (hash_delete(&open_cache,(byte*) unused_tables)) + if (hash_delete(&open_cache,(uchar*) unused_tables)) printf("Warning: Couldn't delete open table from hash\n"); #else - VOID(hash_delete(&open_cache,(byte*) unused_tables)); + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); #endif } /* Free table shares */ while (oldest_unused_share->next) { pthread_mutex_lock(&oldest_unused_share->mutex); - VOID(hash_delete(&table_def_cache, (byte*) oldest_unused_share)); + VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); } } else @@ -1232,7 +1233,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) - VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) { @@ -1271,7 +1272,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) if (table->needs_reopen_or_name_lock() || thd->version != refresh_version || !table->db_stat) { - VOID(hash_delete(&open_cache,(byte*) table)); + VOID(hash_delete(&open_cache,(uchar*) table)); found_old_table=1; } else @@ -1835,7 +1836,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) { if (unlock && thd->locked_tables) mysql_lock_remove(thd, thd->locked_tables,list); - VOID(hash_delete(&open_cache,(byte*) list)); // Close table + VOID(hash_delete(&open_cache,(uchar*) list)); // Close table } else { @@ -2058,9 +2059,9 @@ TABLE *table_cache_insert_placeholder(THD *thd, const char *key, table->in_use= thd; table->locked_by_name=1; - if (my_hash_insert(&open_cache, (byte*)table)) + if (my_hash_insert(&open_cache, (uchar*)table)) { - my_free((gptr) table, MYF(0)); + my_free((uchar*) table, MYF(0)); DBUG_RETURN(NULL); } @@ -2100,7 +2101,7 @@ bool lock_table_name_if_not_cached(THD *thd, const char *db, key_length= (uint)(strmov(strmov(key, db) + 1, table_name) - key) + 1; VOID(pthread_mutex_lock(&LOCK_open)); - if (hash_search(&open_cache, (byte *)key, key_length)) + if (hash_search(&open_cache, (uchar *)key, key_length)) { VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_PRINT("info", ("Table is cached, name-lock is not obtained")); @@ -2227,12 +2228,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); + DBUG_ASSERT (table_list->lock_type != TL_WRITE_DEFAULT); /* find a unused table in the open table cache */ if (refresh) *refresh=0; /* an open table operation needs a lot of the stack space */ - if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (char *)&alias)) + if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (uchar *)&alias)) DBUG_RETURN(0); if (thd->killed) @@ -2393,10 +2395,17 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, VOID(pthread_mutex_unlock(&LOCK_open)); } } - if ((thd->locked_tables) && (thd->locked_tables->lock_count > 0)) - my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); - else + /* + No table in the locked tables list. In case of explicit LOCK TABLES + this can happen if a user did not include the able into the list. + In case of pre-locked mode locked tables list is generated automatically, + so we may only end up here if the table did not exist when + locked tables list was created. + */ + if (thd->prelocked_mode == PRELOCKED) my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias); + else + my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); DBUG_RETURN(0); } @@ -2452,10 +2461,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, an implicit "pending locks queue" - see wait_for_locked_table_names for details. */ - for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, &state); table && table->in_use ; - table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) { /* @@ -2560,7 +2569,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, int error; /* Free cache if too big */ while (open_cache.records > table_cache_size && unused_tables) - VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ if (table_list->create) { @@ -2607,7 +2616,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, mem_root, (flags & OPEN_VIEW_NO_PARSE)); if (error > 0) { - my_free((gptr)table, MYF(0)); + my_free((uchar*)table, MYF(0)); VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(NULL); } @@ -2620,12 +2629,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (error < 0) table_list->view= (st_lex*)1; - my_free((gptr)table, MYF(0)); + my_free((uchar*)table, MYF(0)); VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(0); // VIEW } DBUG_PRINT("info", ("inserting table 0x%lx into the cache", (long) table)); - VOID(my_hash_insert(&open_cache,(byte*) table)); + VOID(my_hash_insert(&open_cache,(uchar*) table)); } check_unused(); // Debugging call @@ -2705,7 +2714,7 @@ TABLE *find_locked_table(THD *thd, const char *db,const char *table_name) 1 error. The old table object is not changed. */ -static bool reopen_table(TABLE *table) +bool reopen_table(TABLE *table) { TABLE tmp; bool error= 1; @@ -2788,27 +2797,55 @@ static bool reopen_table(TABLE *table) } -/* - Used with ALTER TABLE: - Close all instanses of table when LOCK TABLES is in used; - Close first all instances of table and then reopen them +/** + @brief Close all instances of a table open by this thread and replace + them with exclusive name-locks. + + @param thd Thread context + @param db Database name for the table to be closed + @param table_name Name of the table to be closed + + @note This function assumes that if we are not under LOCK TABLES, + then there is only one table open and locked. This means that + the function probably has to be adjusted before it can be used + anywhere outside ALTER TABLE. */ -bool close_data_tables(THD *thd,const char *db, const char *table_name) +void close_data_files_and_morph_locks(THD *thd, const char *db, + const char *table_name) { TABLE *table; - DBUG_ENTER("close_data_tables"); + DBUG_ENTER("close_data_files_and_morph_locks"); + safe_mutex_assert_owner(&LOCK_open); + + if (thd->lock) + { + /* + If we are not under LOCK TABLES we should have only one table + open and locked so it makes sense to remove the lock at once. + */ + mysql_unlock_tables(thd, thd->lock); + thd->lock= 0; + } + + /* + Note that open table list may contain a name-lock placeholder + for target table name if we process ALTER TABLE ... RENAME. + So loop below makes sense even if we are not under LOCK TABLES. + */ for (table=thd->open_tables; table ; table=table->next) { if (!strcmp(table->s->table_name.str, table_name) && !strcmp(table->s->db.str, db)) { - mysql_lock_remove(thd, thd->locked_tables,table); + if (thd->locked_tables) + mysql_lock_remove(thd, thd->locked_tables, table); + table->open_placeholder= 1; close_handle_and_leave_table_as_lock(table); } } - DBUG_RETURN(0); // For the future + DBUG_VOID_RETURN; } @@ -2863,7 +2900,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh) if (!tables || (!db_stat && reopen_table(table))) { my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); - VOID(hash_delete(&open_cache,(byte*) table)); + VOID(hash_delete(&open_cache,(uchar*) table)); error=1; } else @@ -2894,7 +2931,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh) } if (get_locks && tables) { - my_afree((gptr) tables); + my_afree((uchar*) tables); } broadcast_refresh(); *prev=0; @@ -2991,10 +3028,10 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) DBUG_PRINT("loop", ("table_name: %s", table->alias)); HASH_SEARCH_STATE state; - for (TABLE *search= (TABLE*) hash_first(&open_cache, (byte*) key, + for (TABLE *search= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, &state); search ; - search= (TABLE*) hash_next(&open_cache, (byte*) key, + search= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) { DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d " @@ -3108,7 +3145,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name) else { /* We already have a name lock, remove copy */ - VOID(hash_delete(&open_cache,(byte*) table)); + VOID(hash_delete(&open_cache,(uchar*) table)); } } else @@ -3122,7 +3159,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name) broadcast_refresh(); if (thd->locked_tables && thd->locked_tables->table_count == 0) { - my_free((gptr) thd->locked_tables,MYF(0)); + my_free((uchar*) thd->locked_tables,MYF(0)); thd->locked_tables=0; } DBUG_RETURN(found); @@ -3497,6 +3534,12 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) for (tables= *start; tables ;tables= tables->next_global) { safe_to_ignore_table= FALSE; // 'FALSE', as per coding style + + if (tables->lock_type == TL_WRITE_DEFAULT) + { + tables->lock_type= thd->update_lock_default; + DBUG_ASSERT (tables->lock_type >= TL_WRITE_ALLOW_WRITE); + } /* Ignore placeholders for derived tables. After derived tables processing, link to created temporary table will be put here. @@ -3914,6 +3957,148 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table) } +/** + Decide on logging format to use for the statement. + + Compute the capabilities vector for the involved storage engines + and mask out the flags for the binary log. Right now, the binlog + flags only include the capabilities of the storage engines, so this + is safe. + + We now have three alternatives that prevent the statement from + being loggable: + + 1. If there are no capabilities left (all flags are clear) it is + not possible to log the statement at all, so we roll back the + statement and report an error. + + 2. Statement mode is set, but the capabilities indicate that + statement format is not possible. + + 3. Row mode is set, but the capabilities indicate that row + format is not possible. + + 4. Statement is unsafe, but the capabilities indicate that row + format is not possible. + + If we are in MIXED mode, we then decide what logging format to use: + + 1. If the statement is unsafe, row-based logging is used. + + 2. If statement-based logging is not possible, row-based logging is + used. + + 3. Otherwise, statement-based logging is used. + + @param thd Client thread + @param tables Tables involved in the query + */ + +int decide_logging_format(THD *thd, TABLE_LIST *tables) +{ + if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) + { + handler::Table_flags flags_some_set= handler::Table_flags(); + handler::Table_flags flags_all_set= ~handler::Table_flags(); + my_bool multi_engine= FALSE; + void* prev_ht= NULL; + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE) + { + ulonglong const flags= table->table->file->ha_table_flags(); + DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s", + table->table_name, + FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE), + FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE))); + if (prev_ht && prev_ht != table->table->file->ht) + multi_engine= TRUE; + prev_ht= table->table->file->ht; + flags_all_set &= flags; + flags_some_set |= flags; + } + } + + DBUG_PRINT("info", ("flags_all_set: %s%s", + FLAGSTR(flags_all_set, HA_BINLOG_STMT_CAPABLE), + FLAGSTR(flags_all_set, HA_BINLOG_ROW_CAPABLE))); + DBUG_PRINT("info", ("flags_some_set: %s%s", + FLAGSTR(flags_some_set, HA_BINLOG_STMT_CAPABLE), + FLAGSTR(flags_some_set, HA_BINLOG_ROW_CAPABLE))); + DBUG_PRINT("info", ("thd->variables.binlog_format: %ld", + thd->variables.binlog_format)); + DBUG_PRINT("info", ("multi_engine: %s", + multi_engine ? "TRUE" : "FALSE")); + + int error= 0; + if (flags_all_set == 0) + { + my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), + "Statement cannot be logged to the binary log in" + " row-based nor statement-based format"); + } + else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT && + (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) + { + my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), + "Statement-based format required for this statement," + " but not allowed by this combination of engines"); + } + else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW || + thd->lex->is_stmt_unsafe()) && + (flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) + { + my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), + "Row-based format required for this statement," + " but not allowed by this combination of engines"); + } + + /* + If more than one engine is involved in the statement and at + least one is doing it's own logging (is *self-logging*), the + statement cannot be logged atomically, so we generate an error + rather than allowing the binlog to become corrupt. + */ + if (multi_engine && + (flags_some_set & HA_HAS_OWN_BINLOGGING)) + { + error= ER_BINLOG_LOGGING_IMPOSSIBLE; + my_error(error, MYF(0), + "Statement cannot be written atomically since more" + " than one engine involved and at least one engine" + " is self-logging"); + } + + DBUG_PRINT("info", ("error: %d", error)); + + if (error) + { + ha_rollback_stmt(thd); + return -1; + } + + /* + We switch to row-based format if we are in mixed mode and one of + the following are true: + + 1. If the statement is unsafe + 2. If statement format cannot be used + + Observe that point to cannot be decided before the tables + involved in a statement has been checked, i.e., we cannot put + this code in reset_current_stmt_binlog_row_based(), it has to be + here. + */ + if (thd->lex->is_stmt_unsafe() || + (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) + { + thd->set_current_stmt_binlog_row_based_if_mixed(); + } + } + + return 0; +} + /* Lock all tables in list @@ -3952,17 +4137,10 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) in prelocked mode. */ DBUG_ASSERT(!thd->prelocked_mode || !thd->lex->requires_prelocking()); - *need_reopen= FALSE; - /* - CREATE ... SELECT UUID() locks no tables, we have to test here. - */ - if (thd->lex->binlog_row_based_if_mixed) - thd->set_current_stmt_binlog_row_based_if_mixed(); - if (!tables && !thd->lex->requires_prelocking()) - DBUG_RETURN(0); + DBUG_RETURN(decide_logging_format(thd, tables)); /* We need this extra check for thd->prelocked_mode because we want to avoid @@ -3999,7 +4177,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED && has_two_write_locked_tables_with_auto_increment(tables)) { - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); thd->set_current_stmt_binlog_row_based_if_mixed(); } } @@ -4015,6 +4193,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) } DBUG_RETURN(-1); } + if (thd->lex->requires_prelocking() && thd->lex->sql_command != SQLCOM_LOCK_TABLES) { @@ -4081,7 +4260,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES; } } - DBUG_RETURN(0); + + DBUG_RETURN(decide_logging_format(thd, tables)); } @@ -4524,7 +4704,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, field_ptr= table->field + cached_field_index; else if (table->s->name_hash.records) { - field_ptr= (Field**) hash_search(&table->s->name_hash, (byte*) name, + field_ptr= (Field**) hash_search(&table->s->name_hash, (uchar*) name, length); if (field_ptr) { @@ -4732,7 +4912,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, else { if (thd->mark_used_columns == MARK_COLUMNS_READ) - it->walk(&Item::register_field_in_read_map, 1, (byte *) 0); + it->walk(&Item::register_field_in_read_map, 1, (uchar *) 0); } } else @@ -4771,7 +4951,7 @@ Field *find_field_in_table_sef(TABLE *table, const char *name) Field **field_ptr; if (table->s->name_hash.records) { - field_ptr= (Field**)hash_search(&table->s->name_hash,(byte*) name, + field_ptr= (Field**)hash_search(&table->s->name_hash,(uchar*) name, strlen(name)); if (field_ptr) { @@ -6777,7 +6957,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors) table= (*ptr)->table; table->auto_increment_field_not_null= FALSE; } - while ((field = *ptr++)) + while ((field = *ptr++) && !thd->net.report_error) { value=v++; table= field->table; @@ -6863,14 +7043,15 @@ my_bool mysql_rm_tmp_tables(void) (file->name[1] == '.' && !file->name[2]))) continue; - if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) + if (!bcmp((uchar*) file->name, (uchar*) tmp_file_prefix, + tmp_file_prefix_length)) { char *ext= fn_ext(file->name); uint ext_len= strlen(ext); uint filePath_len= my_snprintf(filePath, sizeof(filePath), "%s%c%s", tmpdir, FN_LIBCHAR, file->name); - if (!bcmp(reg_ext, ext, ext_len)) + if (!bcmp((uchar*) reg_ext, (uchar*) ext, ext_len)) { handler *handler_file= 0; /* We should cut file extention before deleting of table */ @@ -6933,7 +7114,7 @@ void remove_db_from_cache(const char *db) } } while (unused_tables && !unused_tables->s->version) - VOID(hash_delete(&open_cache,(byte*) unused_tables)); + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); } @@ -6949,7 +7130,7 @@ void flush_tables() { (void) pthread_mutex_lock(&LOCK_open); while (unused_tables) - hash_delete(&open_cache,(byte*) unused_tables); + hash_delete(&open_cache,(uchar*) unused_tables); (void) pthread_mutex_unlock(&LOCK_open); } @@ -6986,10 +7167,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, HASH_SEARCH_STATE state; result= signalled= 0; - for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, &state); table; - table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) { THD *in_use; @@ -7044,11 +7225,11 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, } } while (unused_tables && !unused_tables->s->version) - VOID(hash_delete(&open_cache,(byte*) unused_tables)); + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); DBUG_PRINT("info", ("Removing table from table_def_cache")); /* Remove table from table definition cache if it's not in use */ - if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(byte*) key, + if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, key_length))) { DBUG_PRINT("info", ("share version: %lu ref_count: %u", @@ -7057,7 +7238,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, if (share->ref_count == 0) { pthread_mutex_lock(&share->mutex); - VOID(hash_delete(&table_def_cache, (byte*) share)); + VOID(hash_delete(&table_def_cache, (uchar*) share)); } } @@ -7299,10 +7480,10 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table key_length=(uint) (strmov(strmov(key,lpt->db)+1,lpt->table_name)-key)+1; VOID(pthread_mutex_lock(&LOCK_open)); HASH_SEARCH_STATE state; - for (table= (TABLE*) hash_first(&open_cache,(byte*) key,key_length, + for (table= (TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state) ; table; - table= (TABLE*) hash_next(&open_cache,(byte*) key,key_length, + table= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state)) { THD *in_use= table->in_use; diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index d3fdd95707c..87224b8eea0 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -33,8 +33,8 @@ void mysql_client_binlog_statement(THD* thd) { DBUG_ENTER("mysql_client_binlog_statement"); DBUG_PRINT("info",("binlog base64: '%*s'", - (thd->lex->comment.length < 2048 ? - thd->lex->comment.length : 2048), + (int) (thd->lex->comment.length < 2048 ? + thd->lex->comment.length : 2048), thd->lex->comment.str)); /* @@ -44,8 +44,8 @@ void mysql_client_binlog_statement(THD* thd) my_bool nsok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; - my_size_t coded_len= thd->lex->comment.length + 1; - my_size_t decoded_len= base64_needed_decoded_length(coded_len); + size_t coded_len= thd->lex->comment.length + 1; + size_t decoded_len= base64_needed_decoded_length(coded_len); DBUG_ASSERT(coded_len > 0); /* @@ -172,6 +172,7 @@ void mysql_client_binlog_statement(THD* thd) not used at all: the rli_fake instance is used only for error reporting. */ +#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) if (IF_DBUG(int err= ) ev->apply_event(thd->rli_fake)) { DBUG_PRINT("info", ("apply_event() returned: %d", err)); @@ -182,6 +183,7 @@ void mysql_client_binlog_statement(THD* thd) my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement"); goto end; } +#endif delete ev; ev= 0; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index bcc4f6a71d3..719c67aff6a 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -365,7 +365,7 @@ TYPELIB query_cache_type_typelib= inline Query_cache_block * Query_cache_block_table::block() { - return (Query_cache_block *)(((byte*)this) - + return (Query_cache_block *)(((uchar*)this) - ALIGN_SIZE(sizeof(Query_cache_block_table)*n) - ALIGN_SIZE(sizeof(Query_cache_block))); } @@ -401,9 +401,9 @@ inline uint Query_cache_block::headers_len() ALIGN_SIZE(sizeof(Query_cache_block))); } -inline gptr Query_cache_block::data(void) +inline uchar* Query_cache_block::data(void) { - return (gptr)( ((byte*)this) + headers_len() ); + return (uchar*)( ((uchar*)this) + headers_len() ); } inline Query_cache_query * Query_cache_block::query() @@ -437,7 +437,7 @@ inline Query_cache_result * Query_cache_block::result() inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n) { return ((Query_cache_block_table *) - (((byte*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) + + (((uchar*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) + n*sizeof(Query_cache_block_table))); } @@ -448,13 +448,13 @@ inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n) extern "C" { -byte *query_cache_table_get_key(const byte *record, uint *length, +uchar *query_cache_table_get_key(const uchar *record, size_t *length, my_bool not_used __attribute__((unused))) { Query_cache_block* table_block = (Query_cache_block*) record; *length = (table_block->used - table_block->headers_len() - ALIGN_SIZE(sizeof(Query_cache_table))); - return (((byte *) table_block->data()) + + return (((uchar *) table_block->data()) + ALIGN_SIZE(sizeof(Query_cache_table))); } } @@ -522,7 +522,7 @@ void Query_cache_query::init_n_lock() my_rwlock_init(&lock, NULL); lock_writing(); DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx", - (long) (((byte*) this) - + (long) (((uchar*) this) - ALIGN_SIZE(sizeof(Query_cache_block))))); DBUG_VOID_RETURN; } @@ -532,7 +532,7 @@ void Query_cache_query::unlock_n_destroy() { DBUG_ENTER("Query_cache_query::unlock_n_destroy"); DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx", - (long) (((byte*) this) - + (long) (((uchar*) this) - ALIGN_SIZE(sizeof(Query_cache_block))))); /* The following call is not needed on system where one can destroy an @@ -546,13 +546,13 @@ void Query_cache_query::unlock_n_destroy() extern "C" { -byte *query_cache_query_get_key(const byte *record, uint *length, +uchar *query_cache_query_get_key(const uchar *record, size_t *length, my_bool not_used) { Query_cache_block *query_block = (Query_cache_block*) record; *length = (query_block->used - query_block->headers_len() - ALIGN_SIZE(sizeof(Query_cache_query))); - return (((byte *) query_block->data()) + + return (((uchar *) query_block->data()) + ALIGN_SIZE(sizeof(Query_cache_query))); } } @@ -639,7 +639,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) done by query_cache.append_result_data if success (if not we need query_cache.structure_guard_mutex locked to free query) */ - if (!query_cache.append_result_data(&result, length, (gptr) packet, + if (!query_cache.append_result_data(&result, length, (uchar*) packet, query_block)) { DBUG_PRINT("warning", ("Can't append data")); @@ -799,12 +799,26 @@ ulong Query_cache::resize(ulong query_cache_size_arg) DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size, query_cache_size_arg)); DBUG_ASSERT(initialized); + STRUCT_LOCK(&structure_guard_mutex); + while (flush_in_progress) + pthread_cond_wait(&COND_flush_finished, &structure_guard_mutex); + flush_in_progress= TRUE; + STRUCT_UNLOCK(&structure_guard_mutex); + free_cache(); + query_cache_size= query_cache_size_arg; - ::query_cache_size= init_cache(); + ulong new_query_cache_size= init_cache(); + + DBUG_EXECUTE("check_querycache",check_integrity(0);); + + STRUCT_LOCK(&structure_guard_mutex); + flush_in_progress= FALSE; + pthread_cond_signal(&COND_flush_finished); STRUCT_UNLOCK(&structure_guard_mutex); - DBUG_RETURN(::query_cache_size); + + DBUG_RETURN(new_query_cache_size); } @@ -932,13 +946,13 @@ def_week_frmt: %lu", /* Check if another thread is processing the same query? */ Query_cache_block *competitor = (Query_cache_block *) - hash_search(&queries, (byte*) thd->query, tot_length); + hash_search(&queries, (uchar*) thd->query, tot_length); DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor)); if (competitor == 0) { /* Query is not in cache and no one is working with it; Store it */ Query_cache_block *query_block; - query_block= write_block_data(tot_length, (gptr) thd->query, + query_block= write_block_data(tot_length, (uchar*) thd->query, ALIGN_SIZE(sizeof(Query_cache_query)), Query_cache_block::QUERY, local_tables, 1); if (query_block != 0) @@ -948,7 +962,7 @@ def_week_frmt: %lu", Query_cache_query *header = query_block->query(); header->init_n_lock(); - if (my_hash_insert(&queries, (byte*) query_block)) + if (my_hash_insert(&queries, (uchar*) query_block)) { refused++; DBUG_PRINT("qcache", ("insertion in query hash")); @@ -961,7 +975,7 @@ def_week_frmt: %lu", { refused++; DBUG_PRINT("warning", ("tables list including failed")); - hash_delete(&queries, (byte *) query_block); + hash_delete(&queries, (uchar *) query_block); header->unlock_n_destroy(); free_memory_block(query_block); STRUCT_UNLOCK(&structure_guard_mutex); @@ -970,7 +984,7 @@ def_week_frmt: %lu", double_linked_list_simple_include(query_block, &queries_blocks); inserts++; queries_in_cache++; - net->query_cache_query= (gptr) query_block; + net->query_cache_query= (uchar*) query_block; header->writer(net); header->tables_type(tables_type); @@ -1140,9 +1154,9 @@ def_week_frmt: %lu", flags.group_concat_max_len, flags.div_precision_increment, flags.default_week_format)); - memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), - &flags, QUERY_CACHE_FLAGS_SIZE); - query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql, + memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), + (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); + query_block = (Query_cache_block *) hash_search(&queries, (uchar*) sql, tot_length); /* Quick abort on unlocked data */ if (query_block == 0 || @@ -1253,7 +1267,7 @@ def_week_frmt: %lu", ("Handler require invalidation queries of %s.%s %lu-%lu", table_list.db, table_list.alias, (ulong) engine_data, (ulong) table->engine_data())); - invalidate_table((byte *) table->db(), table->key_length()); + invalidate_table((uchar *) table->db(), table->key_length()); } else thd->lex->safe_to_cache_query= 0; // Don't try to cache this @@ -1357,7 +1371,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) DUMP(this); for (; tables_used; tables_used= tables_used->next) { - invalidate_table((byte*) tables_used->key, tables_used->key_length); + invalidate_table((uchar*) tables_used->key, tables_used->key_length); DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key, tables_used->key+ strlen(tables_used->key)+1)); @@ -1438,47 +1452,69 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, if (using_transactions) // used for innodb => has_transactions() is TRUE thd->add_changed_table(key, key_length); else - invalidate_table((byte*)key, key_length); + invalidate_table((uchar*)key, key_length); } STRUCT_UNLOCK(&structure_guard_mutex); DBUG_VOID_RETURN; } -/* - Remove all cached queries that uses the given database +/** + @brief Remove all cached queries that uses the given database */ - void Query_cache::invalidate(char *db) { + bool restart= FALSE; DBUG_ENTER("Query_cache::invalidate (db)"); STRUCT_LOCK(&structure_guard_mutex); if (query_cache_size > 0 && !flush_in_progress) { - DUMP(this); - restart_search: if (tables_blocks) { - Query_cache_block *curr= tables_blocks; - Query_cache_block *next; - do - { - next= curr->next; - if (strcmp(db, (char*)(curr->table()->db())) == 0) - invalidate_table(curr); + Query_cache_block *table_block = tables_blocks; + do { + restart= FALSE; + do + { + Query_cache_block *next= table_block->next; + Query_cache_table *table = table_block->table(); + if (strcmp(table->db(),db) == 0) + invalidate_table(table_block); + + table_block= next; + + /* + If our root node to used tables became null then the last element + in the table list was removed when a query was invalidated; + Terminate the search. + */ + if (tables_blocks == 0) + { + table_block= tables_blocks; + } + /* + If the iterated list has changed underlying structure; + we need to restart the search. + */ + else if (table_block->type == Query_cache_block::FREE) + { + restart= TRUE; + table_block= tables_blocks; + } + /* + The used tables are linked in a circular list; + loop until we return to the begining. + */ + } while (table_block != tables_blocks); /* - invalidate_table can freed block on which point 'next' (if - table of this block used only in queries which was deleted - by invalidate_table). As far as we do not allocate new blocks - and mark all headers of freed blocks as 'FREE' (even if they are - merged with other blocks) we can just test type of block - to be sure that block is not deleted + Invalidating a table will also mean that all cached queries using + this table also will be invalidated. This will in turn change the + list of tables associated with these queries and the linked list of + used table will be changed. Because of this we might need to restart + the search when a table has been invalidated. */ - if (next->type == Query_cache_block::FREE) - goto restart_search; - curr= next; - } while (curr != tables_blocks); - } + } while (restart); + } // end if( tables_blocks ) } STRUCT_UNLOCK(&structure_guard_mutex); @@ -1499,8 +1535,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename) uint key_length= filename_2_table_key(key, filename, &db_length); Query_cache_block *table_block; if ((table_block = (Query_cache_block*) hash_search(&tables, - (byte*) key, - key_length))) + (uchar*) key, + key_length))) invalidate_table(table_block); } STRUCT_UNLOCK(&structure_guard_mutex); @@ -1585,8 +1621,9 @@ ulong Query_cache::init_cache() int align; DBUG_ENTER("Query_cache::init_cache"); + approx_additional_data_size = (sizeof(Query_cache) + - sizeof(gptr)*(def_query_hash_size+ + sizeof(uchar*)*(def_query_hash_size+ def_table_hash_size)); if (query_cache_size < approx_additional_data_size) goto err; @@ -1642,7 +1679,7 @@ ulong Query_cache::init_cache() goto err; query_cache_size -= additional_data_size; - if (!(cache= (byte *) + if (!(cache= (uchar *) my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) goto err; @@ -1763,58 +1800,28 @@ void Query_cache::make_disabled() mem_bin_num= mem_bin_steps= 0; queries_in_cache= 0; first_block= 0; + total_blocks= 0; + tables_blocks= 0; DBUG_VOID_RETURN; } -/* - free_cache() - free all resources allocated by the cache. - - SYNOPSIS - free_cache() - - DESCRIPTION - This function frees all resources allocated by the cache. You - have to call init_cache() before using the cache again. +/** + @class Query_cache + @brief Free all resources allocated by the cache. + @details This function frees all resources allocated by the cache. You + have to call init_cache() before using the cache again. This function requires + the structure_guard_mutex to be locked. */ void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); - if (query_cache_size > 0) - flush_cache(); - /* - There may be two free_cache() calls in progress, because we - release 'structure_guard_mutex' in flush_cache(). When the second - flush_cache() wakes up from the wait on 'COND_flush_finished', the - first call to free_cache() has done its job. So we have to test - 'query_cache_size > 0' the second time to see if the cache wasn't - reset by other thread, or if it was reset and was re-enabled then. - If the cache was reset, then we have nothing to do here. - */ - if (query_cache_size > 0) - { -#ifndef DBUG_OFF - if (bins[0].free_blocks == 0) - { - wreck(__LINE__,"no free memory found in (bins[0].free_blocks"); - DBUG_VOID_RETURN; - } -#endif - /* Becasue we did a flush, all cache memory must be in one this block */ - bins[0].free_blocks->destroy(); - total_blocks--; -#ifndef DBUG_OFF - if (free_memory != query_cache_size) - DBUG_PRINT("qcache", ("free memory %lu (should be %lu)", - free_memory , query_cache_size)); -#endif - my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR)); - make_disabled(); - hash_free(&queries); - hash_free(&tables); - } + my_free((uchar*) cache, MYF(MY_ALLOW_ZERO_PTR)); + make_disabled(); + hash_free(&queries); + hash_free(&tables); DBUG_VOID_RETURN; } @@ -2014,7 +2021,7 @@ void Query_cache::free_query(Query_cache_block *query_block) (ulong) query_block, query_block->query()->length() )); - hash_delete(&queries,(byte *) query_block); + hash_delete(&queries,(uchar *) query_block); free_query_internal(query_block); DBUG_VOID_RETURN; @@ -2025,7 +2032,7 @@ void Query_cache::free_query(Query_cache_block *query_block) *****************************************************************************/ Query_cache_block * -Query_cache::write_block_data(ulong data_len, gptr data, +Query_cache::write_block_data(ulong data_len, uchar* data, ulong header_len, Query_cache_block::block_type type, TABLE_COUNTER_TYPE ntab, @@ -2048,8 +2055,7 @@ Query_cache::write_block_data(ulong data_len, gptr data, block->n_tables = ntab; block->used = len; - memcpy((void*) (((byte *) block)+ all_headers_len), - (void*) data, data_len); + memcpy((uchar *) block+ all_headers_len, data, data_len); } DBUG_RETURN(block); } @@ -2061,7 +2067,7 @@ Query_cache::write_block_data(ulong data_len, gptr data, my_bool Query_cache::append_result_data(Query_cache_block **current_block, - ulong data_len, gptr data, + ulong data_len, uchar* data, Query_cache_block *query_block) { DBUG_ENTER("Query_cache::append_result_data"); @@ -2117,7 +2123,7 @@ Query_cache::append_result_data(Query_cache_block **current_block, by the next call */ success = write_result_data(&new_block, data_len-last_block_free_space, - (gptr)(((byte*)data)+last_block_free_space), + (uchar*)(((uchar*)data)+last_block_free_space), query_block, Query_cache_block::RES_CONT); /* @@ -2139,8 +2145,7 @@ Query_cache::append_result_data(Query_cache_block **current_block, ulong to_copy = min(data_len,last_block_free_space); DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub", last_block_free_space, (ulong)last_block, to_copy)); - memcpy((void*) (((byte*) last_block) + last_block->used), (void*) data, - to_copy); + memcpy((uchar*) last_block + last_block->used, data, to_copy); last_block->used+=to_copy; } DBUG_RETURN(success); @@ -2148,7 +2153,7 @@ Query_cache::append_result_data(Query_cache_block **current_block, my_bool Query_cache::write_result_data(Query_cache_block **result_block, - ulong data_len, gptr data, + ulong data_len, uchar* data, Query_cache_block *query_block, Query_cache_block::block_type type) { @@ -2174,7 +2179,7 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, ALIGN_SIZE(sizeof(Query_cache_result))); #ifndef EMBEDDED_LIBRARY Query_cache_block *block= *result_block; - byte *rest= (byte*) data; + uchar *rest= data; // Now fill list of blocks that created by allocate_data_chain do { @@ -2182,7 +2187,7 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, ulong length = block->used - headers_len; DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length, (ulong)block)); - memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length); + memcpy((uchar*) block+headers_len, rest, length); rest += length; block = block->next; type = Query_cache_block::RES_CONT; @@ -2317,18 +2322,18 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) // We don't store temporary tables => no key_length+=4 ... if ((table_block = (Query_cache_block*) - hash_search(&tables,(byte*) key,key_length))) + hash_search(&tables,(uchar*) key,key_length))) invalidate_table(table_block); } } void Query_cache::invalidate_table(TABLE *table) { - invalidate_table((byte*) table->s->table_cache_key.str, + invalidate_table((uchar*) table->s->table_cache_key.str, table->s->table_cache_key.length); } -void Query_cache::invalidate_table(byte * key, uint32 key_length) +void Query_cache::invalidate_table(uchar * key, uint32 key_length) { Query_cache_block *table_block; if ((table_block = ((Query_cache_block*) @@ -2406,12 +2411,13 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, else { DBUG_PRINT("qcache", - ("table: %s db: %s openinfo: 0x%lx keylen: %u key: 0x%lx", + ("table: %s db: %s openinfo: 0x%lx keylen: %lu key: 0x%lx", tables_used->table->s->table_name.str, tables_used->table->s->table_cache_key.str, (ulong) tables_used->table, - tables_used->table->s->table_cache_key.length, + (ulong) tables_used->table->s->table_cache_key.length, (ulong) tables_used->table->s->table_cache_key.str)); + if (!insert_table(tables_used->table->s->table_cache_key.length, tables_used->table->s->table_cache_key.str, block_table, @@ -2478,9 +2484,8 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, n= register_tables_from_list(tables_used, 0, block_table); - if (n) + if (n==0) { - DBUG_PRINT("qcache", ("failed at table %d", (int) n)); /* Unlink the tables we allocated above */ for (Query_cache_block_table *tmp = block->table(0) ; tmp != block_table; @@ -2507,7 +2512,7 @@ Query_cache::insert_table(uint key_len, char *key, (ulong)node, key_len)); Query_cache_block *table_block = ((Query_cache_block *) - hash_search(&tables, (byte*) key, + hash_search(&tables, (uchar*) key, key_len)); if (table_block && @@ -2531,7 +2536,7 @@ Query_cache::insert_table(uint key_len, char *key, { DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)", (ulong) key, (int) key_len)); - table_block = write_block_data(key_len, (gptr) key, + table_block = write_block_data(key_len, (uchar*) key, ALIGN_SIZE(sizeof(Query_cache_table)), Query_cache_block::TABLE, 1, 1); @@ -2546,7 +2551,7 @@ Query_cache::insert_table(uint key_len, char *key, Query_cache_block_table *list_root = table_block->table(0); list_root->n = 0; list_root->next = list_root->prev = list_root; - if (my_hash_insert(&tables, (const byte *) table_block)) + if (my_hash_insert(&tables, (const uchar *) table_block)) { DBUG_PRINT("qcache", ("Can't insert table to hash")); // write_block_data return locked block @@ -2583,7 +2588,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node) Query_cache_block *table_block = neighbour->block(); double_linked_list_exclude(table_block, &tables_blocks); - hash_delete(&tables,(byte *) table_block); + hash_delete(&tables,(uchar *) table_block); free_memory_block(table_block); } DBUG_VOID_RETURN; @@ -2738,7 +2743,7 @@ void Query_cache::free_memory_block(Query_cache_block *block) void Query_cache::split_block(Query_cache_block *block, ulong len) { DBUG_ENTER("Query_cache::split_block"); - Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len); + Query_cache_block *new_block = (Query_cache_block*)(((uchar*) block)+len); new_block->init(block->length - len); total_blocks++; @@ -2970,8 +2975,11 @@ Query_cache::double_linked_list_exclude(Query_cache_block *point, { point->next->prev = point->prev; point->prev->next = point->next; + /* + If the root is removed; select a new root + */ if (point == *list_pointer) - *list_pointer = point->next; + *list_pointer= point->next; } DBUG_VOID_RETURN; } @@ -3171,7 +3179,7 @@ void Query_cache::pack_cache() DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); - byte *border = 0; + uchar *border = 0; Query_cache_block *before = 0; ulong gap = 0; my_bool ok = 1; @@ -3207,7 +3215,7 @@ void Query_cache::pack_cache() } -my_bool Query_cache::move_by_type(byte **border, +my_bool Query_cache::move_by_type(uchar **border, Query_cache_block **before, ulong *gap, Query_cache_block *block) { @@ -3220,7 +3228,7 @@ my_bool Query_cache::move_by_type(byte **border, DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block)); if (*border == 0) { - *border = (byte *) block; + *border = (uchar *) block; *before = block->pprev; DBUG_PRINT("qcache", ("gap beginning here")); } @@ -3250,10 +3258,10 @@ my_bool Query_cache::move_by_type(byte **border, *new_block =(Query_cache_block *) *border; uint tablename_offset = block->table()->table() - block->table()->db(); char *data = (char*) block->data(); - byte *key; - uint key_length; - key=query_cache_table_get_key((byte*) block, &key_length, 0); - hash_first(&tables, (byte*) key, key_length, &record_idx); + uchar *key; + size_t key_length; + key=query_cache_table_get_key((uchar*) block, &key_length, 0); + hash_first(&tables, (uchar*) key, key_length, &record_idx); block->destroy(); new_block->init(len); @@ -3287,7 +3295,7 @@ my_bool Query_cache::move_by_type(byte **border, /* Fix pointer to table name */ new_block->table()->table(new_block->table()->db() + tablename_offset); /* Fix hash to point at moved block */ - hash_replace(&tables, &record_idx, (byte*) new_block); + hash_replace(&tables, &record_idx, (uchar*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); @@ -3310,10 +3318,10 @@ my_bool Query_cache::move_by_type(byte **border, char *data = (char*) block->data(); Query_cache_block *first_result_block = ((Query_cache_query *) block->data())->result(); - byte *key; - uint key_length; - key=query_cache_query_get_key((byte*) block, &key_length, 0); - hash_first(&queries, (byte*) key, key_length, &record_idx); + uchar *key; + size_t key_length; + key=query_cache_query_get_key((uchar*) block, &key_length, 0); + hash_first(&queries, (uchar*) key, key_length, &record_idx); // Move table of used tables memmove((char*) new_block->table(0), (char*) block->table(0), ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); @@ -3329,7 +3337,7 @@ my_bool Query_cache::move_by_type(byte **border, queries_blocks = new_block; Query_cache_block_table *beg_of_table_table= block->table(0), *end_of_table_table= block->table(n_tables); - byte *beg_of_new_table_table= (byte*) new_block->table(0); + uchar *beg_of_new_table_table= (uchar*) new_block->table(0); for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++) { @@ -3339,8 +3347,8 @@ my_bool Query_cache::move_by_type(byte **border, if ((beg_of_table_table <= block_table->next) && (block_table->next < end_of_table_table)) ((Query_cache_block_table *)(beg_of_new_table_table + - (((byte*)block_table->next) - - ((byte*)beg_of_table_table))))->prev= + (((uchar*)block_table->next) - + ((uchar*)beg_of_table_table))))->prev= block_table; else block_table->next->prev= block_table; @@ -3349,8 +3357,8 @@ my_bool Query_cache::move_by_type(byte **border, if ((beg_of_table_table <= block_table->prev) && (block_table->prev < end_of_table_table)) ((Query_cache_block_table *)(beg_of_new_table_table + - (((byte*)block_table->prev) - - ((byte*)beg_of_table_table))))->next= + (((uchar*)block_table->prev) - + ((uchar*)beg_of_table_table))))->next= block_table; else block_table->prev->next = block_table; @@ -3378,10 +3386,10 @@ my_bool Query_cache::move_by_type(byte **border, NET *net = new_block->query()->writer(); if (net != 0) { - net->query_cache_query= (gptr) new_block; + net->query_cache_query= (uchar*) new_block; } /* Fix hash to point at moved block */ - hash_replace(&queries, &record_idx, (byte*) new_block); + hash_replace(&queries, &record_idx, (uchar*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); break; @@ -3517,7 +3525,7 @@ my_bool Query_cache::join_results(ulong join_limit) Query_cache_result *new_result = new_result_block->result(); new_result->parent(block); - byte *write_to = (byte*) new_result->data(); + uchar *write_to = (uchar*) new_result->data(); Query_cache_block *result_block = first_result; do { @@ -3701,18 +3709,18 @@ void Query_cache::queries_dump() Query_cache_block *block = queries_blocks; do { - uint len; - char *str = (char*) query_cache_query_get_key((byte*) block, &len, 0); + size_t len; + char *str = (char*) query_cache_query_get_key((uchar*) block, &len, 0); len-= QUERY_CACHE_FLAGS_SIZE; // Point at flags Query_cache_query_flags flags; memcpy(&flags, str+len, QUERY_CACHE_FLAGS_SIZE); str[len]= 0; // make zero ending DB name - DBUG_PRINT("qcache", ("F: %u C: %u L: %lu T: '%s' (%u) '%s' '%s'", + DBUG_PRINT("qcache", ("F: %u C: %u L: %lu T: '%s' (%lu) '%s' '%s'", flags.client_long_flag, flags.character_set_client_num, (ulong)flags.limit, flags.time_zone->get_name()->ptr(), - len, str, strend(str)+1)); + (ulong) len, str, strend(str)+1)); DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block, (ulong) block->next, (ulong) block->prev, (ulong)block->pnext, (ulong)block->pprev)); @@ -3769,7 +3777,7 @@ void Query_cache::tables_dump() Query_cache_table *table = table_block->table(); DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table())); table_block = table_block->next; - } while ( table_block != tables_blocks); + } while (table_block != tables_blocks); } else DBUG_PRINT("qcache", ("no tables in list")); @@ -3826,25 +3834,25 @@ my_bool Query_cache::check_integrity(bool locked) // Check memory allocation if (block->pnext == first_block) // Is it last block? { - if (((byte*)block) + block->length != - ((byte*)first_block) + query_cache_size) + if (((uchar*)block) + block->length != + ((uchar*)first_block) + query_cache_size) { DBUG_PRINT("error", ("block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx", (ulong) block, (uint) block->type, - (ulong) (((byte*)block) + block->length), - (ulong) (((byte*)first_block) + query_cache_size))); + (ulong) (((uchar*)block) + block->length), + (ulong) (((uchar*)first_block) + query_cache_size))); result = 1; } } else - if (((byte*)block) + block->length != ((byte*)block->pnext)) + if (((uchar*)block) + block->length != ((uchar*)block->pnext)) { DBUG_PRINT("error", ("block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx", (ulong) block, (uint) block->type, - (ulong) (((byte*)block) + block->length), - (ulong) ((byte*)block->pnext))); + (ulong) (((uchar*)block) + block->length), + (ulong) ((uchar*)block->pnext))); } if (block->type == Query_cache_block::FREE) free+= block->length; @@ -3856,8 +3864,8 @@ my_bool Query_cache::check_integrity(bool locked) Query_cache_memory_bin *bin = *((Query_cache_memory_bin **) block->data()); //is it correct pointer? - if (((byte*)bin) < ((byte*)bins) || - ((byte*)bin) >= ((byte*)first_block)) + if (((uchar*)bin) < ((uchar*)bins) || + ((uchar*)bin) >= ((uchar*)first_block)) { DBUG_PRINT("error", ("free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]", @@ -3869,7 +3877,7 @@ my_bool Query_cache::check_integrity(bool locked) } else { - int idx = (((byte*)bin) - ((byte*)bins)) / + int idx = (((uchar*)bin) - ((uchar*)bins)) / sizeof(Query_cache_memory_bin); if (in_list(bins[idx].free_blocks, block, "free memory")) result = 1; @@ -3891,7 +3899,7 @@ my_bool Query_cache::check_integrity(bool locked) Query_cache_block_table *block_table = block->table(j); Query_cache_block_table *block_table_root = (Query_cache_block_table *) - (((byte*)block_table->parent) - + (((uchar*)block_table->parent) - ALIGN_SIZE(sizeof(Query_cache_block_table))); if (in_table_list(block_table, block_table_root, "table list")) @@ -3907,15 +3915,15 @@ my_bool Query_cache::check_integrity(bool locked) case Query_cache_block::RESULT: { Query_cache_block * query_block = block->result()->parent(); - if (((byte*)query_block) < ((byte*)first_block) || - ((byte*)query_block) >= (((byte*)first_block) + query_cache_size)) + if (((uchar*)query_block) < ((uchar*)first_block) || + ((uchar*)query_block) >= (((uchar*)first_block) + query_cache_size)) { DBUG_PRINT("error", ("result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]", (ulong) block, (ulong) query_block, (ulong) first_block, - (ulong) (((byte*)first_block) + query_cache_size))); + (ulong) (((uchar*)first_block) + query_cache_size))); result = 1; } else @@ -3962,10 +3970,10 @@ my_bool Query_cache::check_integrity(bool locked) { DBUG_PRINT("qcache", ("block 0x%lx, type %u...", (ulong) block, (uint) block->type)); - uint length; - byte *key = query_cache_query_get_key((byte*) block, &length, 0); - gptr val = hash_search(&queries, key, length); - if (((gptr)block) != val) + size_t length; + uchar *key = query_cache_query_get_key((uchar*) block, &length, 0); + uchar* val = hash_search(&queries, key, length); + if (((uchar*)block) != val) { DBUG_PRINT("error", ("block 0x%lx found in queries hash like 0x%lx", (ulong) block, (ulong) val)); @@ -3997,10 +4005,10 @@ my_bool Query_cache::check_integrity(bool locked) { DBUG_PRINT("qcache", ("block 0x%lx, type %u...", (ulong) block, (uint) block->type)); - uint length; - byte *key = query_cache_table_get_key((byte*) block, &length, 0); - gptr val = hash_search(&tables, key, length); - if (((gptr)block) != val) + size_t length; + uchar *key = query_cache_table_get_key((uchar*) block, &length, 0); + uchar* val = hash_search(&tables, key, length); + if (((uchar*)block) != val) { DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx", (ulong) block, (ulong) val)); diff --git a/sql/sql_cache.h b/sql/sql_cache.h index bc00f7ea629..3c5d784ce94 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -98,7 +98,7 @@ struct Query_cache_block void init(ulong length); void destroy(); inline uint headers_len(); - inline gptr data(void); + inline uchar* data(void); inline Query_cache_query *query(); inline Query_cache_table *table(); inline Query_cache_result *result(); @@ -128,17 +128,15 @@ struct Query_cache_query inline ulong length() { return len; } inline ulong add(ulong packet_len) { return(len+= packet_len); } inline void length(ulong length_arg) { len= length_arg; } - inline gptr query() + inline uchar* query() { - return (gptr)(((byte*)this)+ - ALIGN_SIZE(sizeof(Query_cache_query))); + return (((uchar*)this) + ALIGN_SIZE(sizeof(Query_cache_query))); } void lock_writing(); void lock_reading(); my_bool try_lock_writing(); void unlock_writing(); void unlock_reading(); - static byte *cache_key(const byte *record, uint *length, my_bool not_used); }; @@ -164,9 +162,9 @@ struct Query_cache_table inline void callback(qc_engine_callback fn){ callback_func= fn; } inline ulonglong engine_data() { return engine_data_buff; } inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; } - inline gptr data() + inline uchar* data() { - return (gptr)(((byte*)this)+ + return (uchar*)(((uchar*)this)+ ALIGN_SIZE(sizeof(Query_cache_table))); } }; @@ -176,9 +174,9 @@ struct Query_cache_result Query_cache_result() {} /* Remove gcc warning */ Query_cache_block *query; - inline gptr data() + inline uchar* data() { - return (gptr)(((byte*) this)+ + return (uchar*)(((uchar*) this)+ ALIGN_SIZE(sizeof(Query_cache_result))); } /* data_continue (if not whole packet contained by this block) */ @@ -189,10 +187,10 @@ struct Query_cache_result extern "C" { - byte *query_cache_query_get_key(const byte *record, uint *length, - my_bool not_used); - byte *query_cache_table_get_key(const byte *record, uint *length, - my_bool not_used); + uchar *query_cache_query_get_key(const uchar *record, size_t *length, + my_bool not_used); + uchar *query_cache_table_get_key(const uchar *record, size_t *length, + my_bool not_used); } extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); @@ -261,7 +259,7 @@ protected: till the end of a flush operation. */ pthread_mutex_t structure_guard_mutex; - byte *cache; // cache memory + uchar *cache; // cache memory Query_cache_block *first_block; // physical location block list Query_cache_block *queries_blocks; // query list (LIFO) Query_cache_block *tables_blocks; @@ -299,7 +297,7 @@ protected: my_bool first_block); void invalidate_table(TABLE_LIST *table); void invalidate_table(TABLE *table); - void invalidate_table(byte *key, uint32 key_length); + void invalidate_table(uchar *key, uint32 key_length); void invalidate_table(Query_cache_block *table_block); TABLE_COUNTER_TYPE register_tables_from_list(TABLE_LIST *tables_used, @@ -324,7 +322,7 @@ protected: ulong add_size); void exclude_from_free_memory_list(Query_cache_block *free_block); void insert_into_free_memory_list(Query_cache_block *new_block); - my_bool move_by_type(byte **border, Query_cache_block **before, + my_bool move_by_type(uchar **border, Query_cache_block **before, ulong *gap, Query_cache_block *i); uint find_bin(ulong size); void move_to_query_list_end(Query_cache_block *block); @@ -346,16 +344,16 @@ protected: ulong init_cache(); void make_disabled(); void free_cache(); - Query_cache_block *write_block_data(ulong data_len, gptr data, + Query_cache_block *write_block_data(ulong data_len, uchar* data, ulong header_len, Query_cache_block::block_type type, TABLE_COUNTER_TYPE ntab = 0, my_bool under_guard=0); my_bool append_result_data(Query_cache_block **result, - ulong data_len, gptr data, + ulong data_len, uchar* data, Query_cache_block *parent); my_bool write_result_data(Query_cache_block **result, - ulong data_len, gptr data, + ulong data_len, uchar* data, Query_cache_block *parent, Query_cache_block::block_type type=Query_cache_block::RESULT); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 87cf9b16d24..119583cab95 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -59,8 +59,8 @@ const char * const THD::DEFAULT_WHERE= "field list"; /* Used templates */ template class List<Key>; template class List_iterator<Key>; -template class List<key_part_spec>; -template class List_iterator<key_part_spec>; +template class List<Key_part_spec>; +template class List_iterator<Key_part_spec>; template class List<Alter_drop>; template class List_iterator<Alter_drop>; template class List<Alter_column>; @@ -71,11 +71,11 @@ template class List_iterator<Alter_column>; ** User variables ****************************************************************************/ -extern "C" byte *get_var_key(user_var_entry *entry, uint *length, - my_bool not_used __attribute__((unused))) +extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length, + my_bool not_used __attribute__((unused))) { - *length=(uint) entry->name.length; - return (byte*) entry->name.str; + *length= entry->name.length; + return (uchar*) entry->name.str; } extern "C" void free_user_var(user_var_entry *entry) @@ -86,11 +86,45 @@ extern "C" void free_user_var(user_var_entry *entry) my_free((char*) entry,MYF(0)); } -bool key_part_spec::operator==(const key_part_spec& other) const +bool Key_part_spec::operator==(const Key_part_spec& other) const { return length == other.length && !strcmp(field_name, other.field_name); } +/** + Construct an (almost) deep copy of this key. Only those + elements that are known to never change are not copied. + If out of memory, a partial copy is returned and an error is set + in THD. +*/ + +Key::Key(const Key &rhs, MEM_ROOT *mem_root) + :type(rhs.type), + key_create_info(rhs.key_create_info), + columns(rhs.columns, mem_root), + name(rhs.name), + generated(rhs.generated) +{ + list_copy_and_replace_each_value(columns, mem_root); +} + +/** + Construct an (almost) deep copy of this foreign key. Only those + elements that are known to never change are not copied. + If out of memory, a partial copy is returned and an error is set + in THD. +*/ + +Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) + :Key(rhs), + ref_table(rhs.ref_table), + ref_columns(rhs.ref_columns), + delete_opt(rhs.delete_opt), + update_opt(rhs.update_opt), + match_opt(rhs.match_opt) +{ + list_copy_and_replace_each_value(ref_columns, mem_root); +} /* Test if a foreign key (= generated key) is a prefix of the given key @@ -126,9 +160,9 @@ bool foreign_key_prefix(Key *a, Key *b) if (a->columns.elements > b->columns.elements) return TRUE; // Can't be prefix - List_iterator<key_part_spec> col_it1(a->columns); - List_iterator<key_part_spec> col_it2(b->columns); - const key_part_spec *col1, *col2; + List_iterator<Key_part_spec> col_it1(a->columns); + List_iterator<Key_part_spec> col_it2(b->columns); + const Key_part_spec *col1, *col2; #ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS while ((col1= col_it1++)) @@ -295,7 +329,7 @@ THD::THD() Open_tables_state(refresh_version), rli_fake(0), lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), - binlog_table_maps(0), + binlog_table_maps(0), binlog_flags(0UL), arg_of_last_insert_id_function(FALSE), first_successful_insert_id_in_prev_stmt(0), first_successful_insert_id_in_prev_stmt_for_binlog(0), @@ -308,7 +342,8 @@ THD::THD() in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), - spcont(NULL) + spcont(NULL), + m_lip(NULL) { ulong tmp; @@ -645,7 +680,7 @@ THD::~THD() void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var) { - ulong *end= (ulong*) ((byte*) to_var + + ulong *end= (ulong*) ((uchar*) to_var + offsetof(STATUS_VAR, last_system_status_var) + sizeof(ulong)); ulong *to= (ulong*) to_var, *from= (ulong*) from_var; @@ -670,7 +705,7 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var) void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var) { - ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR, + ulong *end= (ulong*) ((uchar*) to_var + offsetof(STATUS_VAR, last_system_status_var) + sizeof(ulong)); ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var; @@ -841,9 +876,9 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, CHARSET_INFO *from_cs) { DBUG_ENTER("convert_string"); - size_s new_length= to_cs->mbmaxlen * from_length; + size_t new_length= to_cs->mbmaxlen * from_length; uint dummy_errors; - if (!(to->str= alloc(new_length+1))) + if (!(to->str= (char*) alloc(new_length+1))) { to->length= 0; // Safety fix DBUG_RETURN(1); // EOM @@ -927,7 +962,7 @@ void THD::add_changed_table(TABLE *table) DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && table->file->has_transactions()); add_changed_table(table->s->table_cache_key.str, - table->s->table_cache_key.length); + (long) table->s->table_cache_key.length); DBUG_VOID_RETURN; } @@ -987,8 +1022,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length) return 0; } - new_table->key = (char *) (((byte*)new_table)+ - ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))); + new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST)); new_table->next = 0; new_table->key_length = key_length; ::memcpy(new_table->key, key, key_length); @@ -1423,6 +1457,11 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) } +#define NEED_ESCAPING(x) ((int) (uchar) (x) == escape_char || \ + (int) (uchar) (x) == field_sep_char || \ + (int) (uchar) (x) == line_sep_char || \ + !(x)) + bool select_export::send_data(List<Item> &items) { @@ -1442,7 +1481,7 @@ bool select_export::send_data(List<Item> &items) uint used_length=0,items_left=items.elements; List_iterator_fast<Item> li(items); - if (my_b_write(&cache,(byte*) exchange->line_start->ptr(), + if (my_b_write(&cache,(uchar*) exchange->line_start->ptr(), exchange->line_start->length())) goto err; while ((item=li++)) @@ -1451,7 +1490,7 @@ bool select_export::send_data(List<Item> &items) res=item->str_result(&tmp); if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT)) { - if (my_b_write(&cache,(byte*) exchange->enclosed->ptr(), + if (my_b_write(&cache,(uchar*) exchange->enclosed->ptr(), exchange->enclosed->length())) goto err; } @@ -1463,10 +1502,10 @@ bool select_export::send_data(List<Item> &items) { null_buff[0]=escape_char; null_buff[1]='N'; - if (my_b_write(&cache,(byte*) null_buff,2)) + if (my_b_write(&cache,(uchar*) null_buff,2)) goto err; } - else if (my_b_write(&cache,(byte*) "NULL",4)) + else if (my_b_write(&cache,(uchar*) "NULL",4)) goto err; } else @@ -1482,14 +1521,20 @@ bool select_export::send_data(List<Item> &items) used_length=res->length(); if (result_type == STRING_RESULT && escape_char != -1) { - char *pos,*start,*end; - + char *pos, *start, *end; + CHARSET_INFO *res_charset= res->charset(); + CHARSET_INFO *character_set_client= thd->variables. + character_set_client; + bool check_second_byte= (res_charset == &my_charset_bin) && + character_set_client-> + escape_with_backslash_is_dangerous; + DBUG_ASSERT(character_set_client->mbmaxlen == 2 || + !character_set_client->escape_with_backslash_is_dangerous); for (start=pos=(char*) res->ptr(),end=pos+used_length ; pos != end ; pos++) { #ifdef USE_MB - CHARSET_INFO *res_charset=res->charset(); if (use_mb(res_charset)) { int l; @@ -1500,22 +1545,58 @@ bool select_export::send_data(List<Item> &items) } } #endif - if ((int) *pos == escape_char || (int) *pos == field_sep_char || - (int) *pos == line_sep_char || !*pos) - { + + /* + Special case when dumping BINARY/VARBINARY/BLOB values + for the clients with character sets big5, cp932, gbk and sjis, + which can have the escape character (0x5C "\" by default) + as the second byte of a multi-byte sequence. + + If + - pos[0] is a valid multi-byte head (e.g 0xEE) and + - pos[1] is 0x00, which will be escaped as "\0", + + then we'll get "0xEE + 0x5C + 0x30" in the output file. + + If this file is later loaded using this sequence of commands: + + mysql> create table t1 (a varchar(128)) character set big5; + mysql> LOAD DATA INFILE 'dump.txt' INTO TABLE t1; + + then 0x5C will be misinterpreted as the second byte + of a multi-byte character "0xEE + 0x5C", instead of + escape character for 0x00. + + To avoid this confusion, we'll escape the multi-byte + head character too, so the sequence "0xEE + 0x00" will be + dumped as "0x5C + 0xEE + 0x5C + 0x30". + + Note, in the condition below we only check if + mbcharlen is equal to 2, because there are no + character sets with mbmaxlen longer than 2 + and with escape_with_backslash_is_dangerous set. + DBUG_ASSERT before the loop makes that sure. + */ + + if (NEED_ESCAPING(*pos) || + (check_second_byte && + my_mbcharlen(character_set_client, (uchar) *pos) == 2 && + pos + 1 < end && + NEED_ESCAPING(pos[1]))) + { char tmp_buff[2]; tmp_buff[0]= escape_char; tmp_buff[1]= *pos ? *pos : '0'; - if (my_b_write(&cache,(byte*) start,(uint) (pos-start)) || - my_b_write(&cache,(byte*) tmp_buff,2)) + if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)) || + my_b_write(&cache,(uchar*) tmp_buff,2)) goto err; start=pos+1; } } - if (my_b_write(&cache,(byte*) start,(uint) (pos-start))) + if (my_b_write(&cache,(uchar*) start,(uint) (pos-start))) goto err; } - else if (my_b_write(&cache,(byte*) res->ptr(),used_length)) + else if (my_b_write(&cache,(uchar*) res->ptr(),used_length)) goto err; } if (fixed_row_size) @@ -1531,27 +1612,27 @@ bool select_export::send_data(List<Item> &items) uint length=item->max_length-used_length; for (; length > sizeof(space) ; length-=sizeof(space)) { - if (my_b_write(&cache,(byte*) space,sizeof(space))) + if (my_b_write(&cache,(uchar*) space,sizeof(space))) goto err; } - if (my_b_write(&cache,(byte*) space,length)) + if (my_b_write(&cache,(uchar*) space,length)) goto err; } } if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT)) { - if (my_b_write(&cache, (byte*) exchange->enclosed->ptr(), + if (my_b_write(&cache, (uchar*) exchange->enclosed->ptr(), exchange->enclosed->length())) goto err; } if (--items_left) { - if (my_b_write(&cache, (byte*) exchange->field_term->ptr(), + if (my_b_write(&cache, (uchar*) exchange->field_term->ptr(), field_term_length)) goto err; } } - if (my_b_write(&cache,(byte*) exchange->line_term->ptr(), + if (my_b_write(&cache,(uchar*) exchange->line_term->ptr(), exchange->line_term->length())) goto err; DBUG_RETURN(0); @@ -1598,10 +1679,10 @@ bool select_dump::send_data(List<Item> &items) res=item->str_result(&tmp); if (!res) // If NULL { - if (my_b_write(&cache,(byte*) "",1)) + if (my_b_write(&cache,(uchar*) "",1)) goto err; } - else if (my_b_write(&cache,(byte*) res->ptr(),res->length())) + else if (my_b_write(&cache,(uchar*) res->ptr(),res->length())) { my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno); goto err; @@ -1936,13 +2017,13 @@ Statement::~Statement() C_MODE_START -static byte * -get_statement_id_as_hash_key(const byte *record, uint *key_length, +static uchar * +get_statement_id_as_hash_key(const uchar *record, size_t *key_length, my_bool not_used __attribute__((unused))) { const Statement *statement= (const Statement *) record; *key_length= sizeof(statement->id); - return (byte *) &((const Statement *) statement)->id; + return (uchar *) &((const Statement *) statement)->id; } static void delete_statement_as_hash_key(void *key) @@ -1950,11 +2031,11 @@ static void delete_statement_as_hash_key(void *key) delete (Statement *) key; } -static byte *get_stmt_name_hash_key(Statement *entry, uint *length, +static uchar *get_stmt_name_hash_key(Statement *entry, size_t *length, my_bool not_used __attribute__((unused))) { - *length=(uint) entry->name.length; - return (byte*) entry->name.str; + *length= entry->name.length; + return (uchar*) entry->name.str; } C_MODE_END @@ -1999,7 +2080,7 @@ Statement_map::Statement_map() : int Statement_map::insert(THD *thd, Statement *statement) { - if (my_hash_insert(&st_hash, (byte*) statement)) + if (my_hash_insert(&st_hash, (uchar*) statement)) { /* Delete is needed only in case of an insert failure. In all other @@ -2009,7 +2090,7 @@ int Statement_map::insert(THD *thd, Statement *statement) my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto err_st_hash; } - if (statement->name.str && my_hash_insert(&names_hash, (byte*) statement)) + if (statement->name.str && my_hash_insert(&names_hash, (uchar*) statement)) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto err_names_hash; @@ -2037,9 +2118,9 @@ int Statement_map::insert(THD *thd, Statement *statement) err_max: if (statement->name.str) - hash_delete(&names_hash, (byte*) statement); + hash_delete(&names_hash, (uchar*) statement); err_names_hash: - hash_delete(&st_hash, (byte*) statement); + hash_delete(&st_hash, (uchar*) statement); err_st_hash: return 1; } @@ -2060,9 +2141,9 @@ void Statement_map::erase(Statement *statement) if (statement == last_found_statement) last_found_statement= 0; if (statement->name.str) - hash_delete(&names_hash, (byte *) statement); + hash_delete(&names_hash, (uchar *) statement); - hash_delete(&st_hash, (byte *) statement); + hash_delete(&st_hash, (uchar *) statement); pthread_mutex_lock(&LOCK_prepared_stmt_count); DBUG_ASSERT(prepared_stmt_count > 0); prepared_stmt_count--; @@ -2477,7 +2558,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) pthread_mutex_t LOCK_xid_cache; HASH xid_cache; -static byte *xid_get_hash_key(const byte *ptr,uint *length, +static uchar *xid_get_hash_key(const uchar *ptr, size_t *length, my_bool not_used __attribute__((unused))) { *length=((XID_STATE*)ptr)->xid.key_length(); @@ -2487,7 +2568,7 @@ static byte *xid_get_hash_key(const byte *ptr,uint *length, static void xid_free_hash (void *ptr) { if (!((XID_STATE*)ptr)->in_thd) - my_free((gptr)ptr, MYF(0)); + my_free((uchar*)ptr, MYF(0)); } bool xid_cache_init() @@ -2529,7 +2610,7 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state) xs->xa_state=xa_state; xs->xid.set(xid); xs->in_thd=0; - res=my_hash_insert(&xid_cache, (byte*)xs); + res=my_hash_insert(&xid_cache, (uchar*)xs); } pthread_mutex_unlock(&LOCK_xid_cache); return res; @@ -2541,7 +2622,7 @@ bool xid_cache_insert(XID_STATE *xid_state) pthread_mutex_lock(&LOCK_xid_cache); DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(), xid_state->xid.key_length())==0); - my_bool res=my_hash_insert(&xid_cache, (byte*)xid_state); + my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state); pthread_mutex_unlock(&LOCK_xid_cache); return res; } @@ -2550,7 +2631,7 @@ bool xid_cache_insert(XID_STATE *xid_state) void xid_cache_delete(XID_STATE *xid_state) { pthread_mutex_lock(&LOCK_xid_cache); - hash_delete(&xid_cache, (byte *)xid_state); + hash_delete(&xid_cache, (uchar *)xid_state); pthread_mutex_unlock(&LOCK_xid_cache); } @@ -2586,8 +2667,8 @@ void xid_cache_delete(XID_STATE *xid_state) template <class RowsEventT> Rows_log_event* THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, MY_BITMAP const* cols, - my_size_t colcnt, - my_size_t needed, + size_t colcnt, + size_t needed, bool is_transactional, RowsEventT *hint __attribute__((unused))) { @@ -2657,17 +2738,17 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, */ template Rows_log_event* THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, - my_size_t, my_size_t, bool, + size_t, size_t, bool, Write_rows_log_event*); template Rows_log_event* THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, - my_size_t colcnt, my_size_t, bool, + size_t colcnt, size_t, bool, Delete_rows_log_event *); template Rows_log_event* THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, - my_size_t colcnt, my_size_t, bool, + size_t colcnt, size_t, bool, Update_rows_log_event *); #endif @@ -2736,27 +2817,6 @@ field_type_name(enum_field_types type) #endif -my_size_t THD::max_row_length_blob(TABLE *table, const byte *data) const -{ - my_size_t length= 0; - TABLE_SHARE *table_s= table->s; - uint* const beg= table_s->blob_field; - uint* const end= beg + table_s->blob_fields; - - for (uint *ptr= beg ; ptr != end ; ++ptr) - { - Field_blob* const blob= (Field_blob*) table->field[*ptr]; - length+= blob->get_length((const char*) (data + - blob->offset(table->record[0]))) + - HA_KEY_BLOB_LENGTH; - } - - return length; -} - - - - namespace { /** Class to handle temporary allocation of memory for row data. @@ -2785,7 +2845,7 @@ namespace { @param length Length of data that is needed, if the record contain blobs. */ - Row_data_memory(TABLE *table, my_size_t const len1) + Row_data_memory(TABLE *table, size_t const len1) : m_memory(0) { #ifndef DBUG_OFF @@ -2796,7 +2856,7 @@ namespace { m_ptr[1]= 0; } - Row_data_memory(TABLE *table, my_size_t const len1, my_size_t const len2) + Row_data_memory(TABLE *table, size_t const len1, size_t const len2) : m_memory(0) { #ifndef DBUG_OFF @@ -2810,7 +2870,7 @@ namespace { ~Row_data_memory() { if (m_memory != 0 && m_release_memory_on_destruction) - my_free((gptr) m_memory, MYF(MY_WME)); + my_free((uchar*) m_memory, MYF(MY_WME)); } /** @@ -2826,7 +2886,7 @@ namespace { return m_memory != 0; } - byte *slot(uint s) + uchar *slot(uint s) { DBUG_ASSERT(s < sizeof(m_ptr)/sizeof(*m_ptr)); DBUG_ASSERT(m_ptr[s] != 0); @@ -2835,7 +2895,7 @@ namespace { } private: - void allocate_memory(TABLE *const table, my_size_t const total_length) + void allocate_memory(TABLE *const table, size_t const total_length) { if (table->s->blob_fields == 0) { @@ -2849,7 +2909,7 @@ namespace { to add two bytes for each field, which can potentially be added to hold the length of a packed field. */ - my_size_t const maxlen= table->s->reclength + 2 * table->s->fields; + size_t const maxlen= table->s->reclength + 2 * table->s->fields; /* Allocate memory for two records if memory hasn't been @@ -2858,13 +2918,13 @@ namespace { */ if (table->write_row_record == 0) table->write_row_record= - (byte *) alloc_root(&table->mem_root, 2 * maxlen); + (uchar *) alloc_root(&table->mem_root, 2 * maxlen); m_memory= table->write_row_record; m_release_memory_on_destruction= FALSE; } else { - m_memory= (byte *) my_malloc(total_length, MYF(MY_WME)); + m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME)); m_release_memory_on_destruction= TRUE; } } @@ -2873,15 +2933,15 @@ namespace { mutable bool m_alloc_checked; #endif bool m_release_memory_on_destruction; - byte *m_memory; - byte *m_ptr[2]; + uchar *m_memory; + uchar *m_ptr[2]; }; } int THD::binlog_write_row(TABLE* table, bool is_trans, - MY_BITMAP const* cols, my_size_t colcnt, - byte const *record) + MY_BITMAP const* cols, size_t colcnt, + uchar const *record) { DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); @@ -2893,9 +2953,9 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, if (!memory.has_memory()) return HA_ERR_OUT_OF_MEM; - byte *row_data= memory.slot(0); + uchar *row_data= memory.slot(0); - my_size_t const len= pack_row(table, cols, row_data, record); + size_t const len= pack_row(table, cols, row_data, record); Rows_log_event* const ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, @@ -2909,25 +2969,25 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, } int THD::binlog_update_row(TABLE* table, bool is_trans, - MY_BITMAP const* cols, my_size_t colcnt, - const byte *before_record, - const byte *after_record) + MY_BITMAP const* cols, size_t colcnt, + const uchar *before_record, + const uchar *after_record) { DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); - my_size_t const before_maxlen = max_row_length(table, before_record); - my_size_t const after_maxlen = max_row_length(table, after_record); + size_t const before_maxlen = max_row_length(table, before_record); + size_t const after_maxlen = max_row_length(table, after_record); Row_data_memory row_data(table, before_maxlen, after_maxlen); if (!row_data.has_memory()) return HA_ERR_OUT_OF_MEM; - byte *before_row= row_data.slot(0); - byte *after_row= row_data.slot(1); + uchar *before_row= row_data.slot(0); + uchar *after_row= row_data.slot(1); - my_size_t const before_size= pack_row(table, cols, before_row, + size_t const before_size= pack_row(table, cols, before_row, before_record); - my_size_t const after_size= pack_row(table, cols, after_row, + size_t const after_size= pack_row(table, cols, after_row, after_record); /* @@ -2935,10 +2995,10 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, trigger false warnings. */ #ifndef HAVE_purify - DBUG_DUMP("before_record", (const char *)before_record, table->s->reclength); - DBUG_DUMP("after_record", (const char *)after_record, table->s->reclength); - DBUG_DUMP("before_row", (const char *)before_row, before_size); - DBUG_DUMP("after_row", (const char *)after_row, after_size); + DBUG_DUMP("before_record", before_record, table->s->reclength); + DBUG_DUMP("after_record", after_record, table->s->reclength); + DBUG_DUMP("before_row", before_row, before_size); + DBUG_DUMP("after_row", after_row, after_size); #endif Rows_log_event* const ev= @@ -2955,8 +3015,8 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, } int THD::binlog_delete_row(TABLE* table, bool is_trans, - MY_BITMAP const* cols, my_size_t colcnt, - byte const *record) + MY_BITMAP const* cols, size_t colcnt, + uchar const *record) { DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); @@ -2968,9 +3028,9 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, if (unlikely(!memory.has_memory())) return HA_ERR_OUT_OF_MEM; - byte *row_data= memory.slot(0); + uchar *row_data= memory.slot(0); - my_size_t const len= pack_row(table, cols, row_data, record); + size_t const len= pack_row(table, cols, row_data, record); Rows_log_event* const ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, @@ -3048,9 +3108,9 @@ void THD::binlog_delete_pending_rows_event() RETURN VALUE Error code, or 0 if no error. */ -int THD::binlog_query(THD::enum_binlog_query_type qtype, - char const *query, ulong query_len, - bool is_trans, bool suppress_use) +int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query, + ulong query_len, bool is_trans, bool suppress_use, + THD::killed_state killed_status_arg) { DBUG_ENTER("THD::binlog_query"); DBUG_PRINT("enter", ("qtype=%d, query='%s'", qtype, query)); @@ -3069,6 +3129,27 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, if (int error= binlog_flush_pending_rows_event(TRUE)) DBUG_RETURN(error); + /* + If we are in statement mode and trying to log an unsafe statement, + we should print a warning. + */ + if (lex->is_stmt_unsafe() && + variables.binlog_format == BINLOG_FORMAT_STMT) + { + DBUG_ASSERT(this->query != NULL); + push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_BINLOG_UNSAFE_STATEMENT, + ER(ER_BINLOG_UNSAFE_STATEMENT)); + if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) + { + char warn_buf[MYSQL_ERRMSG_SIZE]; + my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", + ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); + sql_print_warning(warn_buf); + binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; + } + } + switch (qtype) { case THD::ROW_QUERY_TYPE: if (current_stmt_binlog_row_based) @@ -3089,7 +3170,8 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, flush the pending rows event if necessary. */ { - Query_log_event qinfo(this, query, query_len, is_trans, suppress_use); + Query_log_event qinfo(this, query, query_len, is_trans, suppress_use, + killed_status_arg); qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; /* Binlog table maps will be irrelevant after a Query_log_event diff --git a/sql/sql_class.h b/sql/sql_class.h index ba0defcf875..0f42a4c9988 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -73,6 +73,7 @@ typedef struct st_copy_info { ha_rows updated; ha_rows copied; ha_rows error_count; + ha_rows touched; /* Number of touched records */ enum enum_duplicates handle_duplicates; int escape_char, last_errno; bool ignore; @@ -84,12 +85,23 @@ typedef struct st_copy_info { } COPY_INFO; -class key_part_spec :public Sql_alloc { +class Key_part_spec :public Sql_alloc { public: const char *field_name; uint length; - key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {} - bool operator==(const key_part_spec& other) const; + Key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {} + bool operator==(const Key_part_spec& other) const; + /** + Construct a copy of this Key_part_spec. field_name is copied + by-pointer as it is known to never change. At the same time + 'length' may be reset in mysql_prepare_create_table, and this + is why we supply it with a copy. + + @return If out of memory, 0 is returned and an error is set in + THD. + */ + Key_part_spec *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Key_part_spec(*this); } }; @@ -100,6 +112,12 @@ public: enum drop_type type; Alter_drop(enum drop_type par_type,const char *par_name) :name(par_name), type(par_type) {} + /** + Used to make a clone of this object for ALTER/CREATE TABLE + @sa comment for Key_part_spec::clone + */ + Alter_drop *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Alter_drop(*this); } }; @@ -109,6 +127,12 @@ public: Item *def; Alter_column(const char *par_name,Item *literal) :name(par_name), def(literal) {} + /** + Used to make a clone of this object for ALTER/CREATE TABLE + @sa comment for Key_part_spec::clone + */ + Alter_column *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Alter_column(*this); } }; @@ -117,24 +141,31 @@ public: enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY}; enum Keytype type; KEY_CREATE_INFO key_create_info; - List<key_part_spec> columns; + List<Key_part_spec> columns; const char *name; bool generated; Key(enum Keytype type_par, const char *name_arg, KEY_CREATE_INFO *key_info_arg, - bool generated_arg, List<key_part_spec> &cols) + bool generated_arg, List<Key_part_spec> &cols) :type(type_par), key_create_info(*key_info_arg), columns(cols), name(name_arg), generated(generated_arg) {} - ~Key() {} + Key(const Key &rhs, MEM_ROOT *mem_root); + virtual ~Key() {} /* Equality comparison of keys (ignoring name) */ friend bool foreign_key_prefix(Key *a, Key *b); + /** + Used to make a clone of this object for ALTER/CREATE TABLE + @sa comment for Key_part_spec::clone + */ + virtual Key *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Key(*this, mem_root); } }; class Table_ident; -class foreign_key: public Key { +class Foreign_key: public Key { public: enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL, FK_MATCH_PARTIAL, FK_MATCH_SIMPLE}; @@ -142,16 +173,23 @@ public: FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT}; Table_ident *ref_table; - List<key_part_spec> ref_columns; + List<Key_part_spec> ref_columns; uint delete_opt, update_opt, match_opt; - foreign_key(const char *name_arg, List<key_part_spec> &cols, - Table_ident *table, List<key_part_spec> &ref_cols, + Foreign_key(const char *name_arg, List<Key_part_spec> &cols, + Table_ident *table, List<Key_part_spec> &ref_cols, uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg) :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols), ref_table(table), ref_columns(cols), delete_opt(delete_opt_arg), update_opt(update_opt_arg), match_opt(match_opt_arg) {} + Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root); + /** + Used to make a clone of this object for ALTER/CREATE TABLE + @sa comment for Key_part_spec::clone + */ + virtual Key *clone(MEM_ROOT *mem_root) const + { return new (mem_root) Foreign_key(*this, mem_root); } }; typedef struct st_mysql_lock @@ -306,8 +344,8 @@ struct system_variables typedef struct system_status_var { - ulong bytes_received; - ulong bytes_sent; + ulonglong bytes_received; + ulonglong bytes_sent; ulong com_other; ulong com_stat[(uint) SQLCOM_END]; ulong created_tmp_disk_tables; @@ -435,30 +473,31 @@ public: inline bool is_conventional() const { return state == CONVENTIONAL_EXECUTION; } - inline gptr alloc(unsigned int size) { return alloc_root(mem_root,size); } - inline gptr calloc(unsigned int size) + inline void* alloc(size_t size) { return alloc_root(mem_root,size); } + inline void* calloc(size_t size) { - gptr ptr; + void *ptr; if ((ptr=alloc_root(mem_root,size))) - bzero((char*) ptr,size); + bzero(ptr, size); return ptr; } inline char *strdup(const char *str) { return strdup_root(mem_root,str); } - inline char *strmake(const char *str, uint size) + inline char *strmake(const char *str, size_t size) { return strmake_root(mem_root,str,size); } - inline bool LEX_STRING_make(LEX_STRING *lex_str, const char *str, uint size) + inline bool LEX_STRING_make(LEX_STRING *lex_str, const char *str, + size_t size) { return ((lex_str->str= strmake_root(mem_root, str, (lex_str->length= size)))) == 0; } - inline char *memdup(const char *str, uint size) + inline void *memdup(const void *str, size_t size) { return memdup_root(mem_root,str,size); } - inline char *memdup_w_gap(const char *str, uint size, uint gap) + inline void *memdup_w_gap(const void *str, size_t size, uint gap) { - gptr ptr; - if ((ptr=alloc_root(mem_root,size+gap))) + void *ptr; + if ((ptr= alloc_root(mem_root,size+gap))) memcpy(ptr,str,size); return ptr; } @@ -580,7 +619,7 @@ public: Statement *find_by_name(LEX_STRING *name) { Statement *stmt; - stmt= (Statement*)hash_search(&names_hash, (byte*)name->str, + stmt= (Statement*)hash_search(&names_hash, (uchar*)name->str, name->length); return stmt; } @@ -590,7 +629,7 @@ public: if (last_found_statement == 0 || id != last_found_statement->id) { Statement *stmt; - stmt= (Statement *) hash_search(&st_hash, (byte *) &id, sizeof(id)); + stmt= (Statement *) hash_search(&st_hash, (uchar *) &id, sizeof(id)); if (stmt && stmt->name.str) return NULL; last_found_statement= stmt; @@ -1033,14 +1072,14 @@ public: void binlog_set_stmt_begin(); int binlog_write_table_map(TABLE *table, bool is_transactional); int binlog_write_row(TABLE* table, bool is_transactional, - MY_BITMAP const* cols, my_size_t colcnt, - const byte *buf); + MY_BITMAP const* cols, size_t colcnt, + const uchar *buf); int binlog_delete_row(TABLE* table, bool is_transactional, - MY_BITMAP const* cols, my_size_t colcnt, - const byte *buf); + MY_BITMAP const* cols, size_t colcnt, + const uchar *buf); int binlog_update_row(TABLE* table, bool is_transactional, - MY_BITMAP const* cols, my_size_t colcnt, - const byte *old_data, const byte *new_data); + MY_BITMAP const* cols, size_t colcnt, + const uchar *old_data, const uchar *new_data); void set_server_id(uint32 sid) { server_id = sid; } @@ -1050,61 +1089,34 @@ public: template <class RowsEventT> Rows_log_event* binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, MY_BITMAP const* cols, - my_size_t colcnt, - my_size_t needed, + size_t colcnt, + size_t needed, bool is_transactional, RowsEventT* hint); Rows_log_event* binlog_get_pending_rows_event() const; void binlog_set_pending_rows_event(Rows_log_event* ev); - - my_size_t max_row_length_blob(TABLE* table, const byte *data) const; - my_size_t max_row_length(TABLE* table, const byte *data) const - { - TABLE_SHARE *table_s= table->s; - my_size_t length= table_s->reclength + 2 * table_s->fields; - if (table_s->blob_fields == 0) - return length; - - return (length+max_row_length_blob(table,data)); - } - int binlog_flush_pending_rows_event(bool stmt_end); void binlog_delete_pending_rows_event(); private: uint binlog_table_maps; // Number of table maps currently in the binlog + + enum enum_binlog_flag { + BINLOG_FLAG_UNSAFE_STMT_PRINTED, + BINLOG_FLAG_COUNT + }; + + /** + Flags with per-thread information regarding the status of the + binary log. + */ + uint32 binlog_flags; public: uint get_binlog_table_maps() const { return binlog_table_maps; } #endif /* MYSQL_CLIENT */ -#ifndef MYSQL_CLIENT -public: - enum enum_binlog_query_type { - /* - The query can be logged row-based or statement-based - */ - ROW_QUERY_TYPE, - - /* - The query has to be logged statement-based - */ - STMT_QUERY_TYPE, - - /* - The query represents a change to a table in the "mysql" - database and is currently mapped to ROW_QUERY_TYPE. - */ - MYSQL_QUERY_TYPE, - QUERY_TYPE_COUNT - }; - - int binlog_query(enum_binlog_query_type qtype, - char const *query, ulong query_len, - bool is_trans, bool suppress_use); -#endif - public: struct st_transactions { @@ -1359,7 +1371,14 @@ public: DYNAMIC_ARRAY user_var_events; /* For user variables replication */ MEM_ROOT *user_var_events_alloc; /* Allocate above array elements here */ - enum killed_state { NOT_KILLED=0, KILL_BAD_DATA=1, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED }; + enum killed_state + { + NOT_KILLED=0, + KILL_BAD_DATA=1, + KILL_CONNECTION=ER_SERVER_SHUTDOWN, + KILL_QUERY=ER_QUERY_INTERRUPTED, + KILLED_NO_VALUE /* means neither of the states */ + }; killed_state volatile killed; /* scramble - random string sent to client on handshake */ @@ -1484,6 +1503,33 @@ public: void close_active_vio(); #endif void awake(THD::killed_state state_to_set); + +#ifndef MYSQL_CLIENT + enum enum_binlog_query_type { + /* + The query can be logged row-based or statement-based + */ + ROW_QUERY_TYPE, + + /* + The query has to be logged statement-based + */ + STMT_QUERY_TYPE, + + /* + The query represents a change to a table in the "mysql" + database and is currently mapped to ROW_QUERY_TYPE. + */ + MYSQL_QUERY_TYPE, + QUERY_TYPE_COUNT + }; + + int binlog_query(enum_binlog_query_type qtype, + char const *query, ulong query_len, + bool is_trans, bool suppress_use, + THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE); +#endif + /* For enter_cond() / exit_cond() to work the mutex must be got before enter_cond(); this mutex is then released by exit_cond(). @@ -1539,7 +1585,7 @@ public: { return !stmt_arena->is_stmt_prepare(); } - inline gptr trans_alloc(unsigned int size) + inline void* trans_alloc(unsigned int size) { return alloc_root(&transaction.mem_root,size); } @@ -1610,7 +1656,8 @@ public: void end_statement(); inline int killed_errno() const { - return killed != KILL_BAD_DATA ? killed : 0; + killed_state killed_val; /* to cache the volatile 'killed' */ + return (killed_val= killed) != KILL_BAD_DATA ? killed_val : 0; } inline void send_kill_message() const { @@ -1634,6 +1681,7 @@ public: void restore_sub_statement_state(Sub_statement_state *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup); + inline void set_current_stmt_binlog_row_based_if_mixed() { /* @@ -1690,7 +1738,7 @@ public: This way the user will notice the error as there will be no current database selected (in addition to the error message set by malloc). */ - bool set_db(const char *new_db, uint new_db_len) + bool set_db(const char *new_db, size_t new_db_len) { /* Do not reallocate memory if current chunk is big enough. */ if (db && new_db && db_length >= new_db_len) @@ -1703,7 +1751,7 @@ public: db_length= db ? new_db_len : 0; return new_db && !db; } - void reset_db(char *new_db, uint new_db_len) + void reset_db(char *new_db, size_t new_db_len) { db= new_db; db_length= new_db_len; @@ -1713,7 +1761,7 @@ public: allocate memory for a deep copy: current database may be freed after a statement is parsed but before it's executed. */ - bool copy_db_to(char **p_db, uint *p_db_length) + bool copy_db_to(char **p_db, size_t *p_db_length) { if (db == NULL) { @@ -1944,19 +1992,21 @@ class select_insert :public select_result_interceptor { class select_create: public select_insert { ORDER *group; TABLE_LIST *create_table; - List<create_field> *extra_fields; - List<Key> *keys; + TABLE_LIST *select_tables; HA_CREATE_INFO *create_info; + Alter_info *alter_info; Field **field; public: select_create (TABLE_LIST *table_arg, HA_CREATE_INFO *create_info_par, - List<create_field> &fields_par, - List<Key> &keys_par, - List<Item> &select_fields,enum_duplicates duplic, bool ignore) + Alter_info *alter_info_arg, + List<Item> &select_fields,enum_duplicates duplic, bool ignore, + TABLE_LIST *select_tables_arg) :select_insert (NULL, NULL, &select_fields, 0, 0, duplic, ignore), - create_table(table_arg), extra_fields(&fields_par),keys(&keys_par), - create_info(create_info_par) + create_table(table_arg), + create_info(create_info_par), + select_tables(select_tables_arg), + alter_info(alter_info_arg) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); @@ -1992,7 +2042,7 @@ public: List<Item> save_copy_funcs; Copy_field *copy_field, *copy_field_end; Copy_field *save_copy_field, *save_copy_field_end; - byte *group_buff; + uchar *group_buff; Item **items_to_copy; /* Fields in tmp table */ MI_COLUMNDEF *recinfo,*start_recinfo; KEY *keyinfo; @@ -2198,7 +2248,7 @@ class Unique :public Sql_alloc ulonglong max_in_memory_size; IO_CACHE file; TREE tree; - byte *record_pointers; + uchar *record_pointers; bool flush(); uint size; @@ -2231,8 +2281,8 @@ public: void reset(); bool walk(tree_walk_action action, void *walk_action_arg); - friend int unique_write_to_file(gptr key, element_count count, Unique *unique); - friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique); + friend int unique_write_to_file(uchar* key, element_count count, Unique *unique); + friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique); }; @@ -2273,6 +2323,11 @@ class multi_update :public select_result_interceptor List <Item> *fields, *values; List <Item> **fields_for_table, **values_for_table; uint table_count; + /* + List of tables referenced in the CHECK OPTION condition of + the updated view excluding the updated table. + */ + List <TABLE> unupdated_check_opt_tables; Copy_field *copy_field; enum enum_duplicates handle_duplicates; bool do_update, trans_safe; diff --git a/sql/sql_client.cc b/sql/sql_client.cc index d6f1183806e..032a2e26e3a 100644 --- a/sql/sql_client.cc +++ b/sql/sql_client.cc @@ -28,8 +28,11 @@ void my_net_local_init(NET *net) { #ifndef EMBEDDED_LIBRARY net->max_packet= (uint) global_system_variables.net_buffer_length; - net->read_timeout= (uint) global_system_variables.net_read_timeout; - net->write_timeout=(uint) global_system_variables.net_write_timeout; + + my_net_set_read_timeout(net, (uint)global_system_variables.net_read_timeout); + my_net_set_write_timeout(net, + (uint)global_system_variables.net_write_timeout); + net->retry_count= (uint) global_system_variables.net_retry_count; net->max_packet_size= max(global_system_variables.net_buffer_length, global_system_variables.max_allowed_packet); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 6c07c6ba6d5..26b7098e27c 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -80,7 +80,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; (void) pthread_mutex_lock(&LOCK_user_conn); if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len))) + (uchar*) temp_user, temp_len))) { /* First connection for user; Create a user connection object */ if (!(uc= ((struct user_conn*) @@ -98,7 +98,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0; uc->user_resources= *mqh; uc->intime= thd->thr_create_time; - if (my_hash_insert(&hash_user_connections, (byte*) uc)) + if (my_hash_insert(&hash_user_connections, (uchar*) uc)) { my_free((char*) uc,0); net_send_error(thd, 0, NullS); // Out of memory @@ -200,7 +200,7 @@ void decrease_user_connections(USER_CONN *uc) if (!--uc->connections && !mqh_used) { /* Last connection for user; Delete it */ - (void) hash_delete(&hash_user_connections,(byte*) uc); + (void) hash_delete(&hash_user_connections,(uchar*) uc); } (void) pthread_mutex_unlock(&LOCK_user_conn); DBUG_VOID_RETURN; @@ -512,11 +512,11 @@ int check_user(THD *thd, enum enum_server_command command, started with corresponding variable that is greater then 0. */ -extern "C" byte *get_key_conn(user_conn *buff, uint *length, +extern "C" uchar *get_key_conn(user_conn *buff, size_t *length, my_bool not_used __attribute__((unused))) { - *length=buff->len; - return (byte*) buff->user; + *length= buff->len; + return (uchar*) buff->user; } @@ -559,7 +559,7 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0) memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length); temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0; if ((uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len))) + (uchar*) temp_user, temp_len))) { uc->questions=0; get_mqh(temp_user,&temp_user[lu->user.length+1],uc); @@ -747,8 +747,8 @@ static int check_connection(THD *thd) SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1; /* At this point we write connection message and read reply */ - if (net_write_command(net, (uchar) protocol_version, "", 0, buff, - (uint) (end-buff)) || + if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0, + (uchar*) buff, (size_t) (end-buff)) || (pkt_len= my_net_read(net)) == packet_error || pkt_len < MIN_HANDSHAKE_SIZE) { @@ -837,9 +837,12 @@ static int check_connection(THD *thd) password both send '\0'. This strlen() can't be easily deleted without changing protocol. + + Cast *passwd to an unsigned char, so that it doesn't extend the sign for + *passwd > 127 and become 2**32-127+ after casting to uint. */ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - *passwd++ : strlen(passwd); + (uchar)(*passwd++) : strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; /* strlen() can't be easily deleted without changing protocol */ @@ -936,8 +939,8 @@ bool login_connection(THD *thd) net->no_send_error= 0; /* Use "connect_timeout" value during connection phase */ - net_set_read_timeout(net, connect_timeout); - net_set_write_timeout(net, connect_timeout); + my_net_set_read_timeout(net, connect_timeout); + my_net_set_write_timeout(net, connect_timeout); if ((error=check_connection(thd))) { // Wrong permissions @@ -951,8 +954,8 @@ bool login_connection(THD *thd) DBUG_RETURN(1); } /* Connect completed, set read/write timeouts back to default */ - net_set_read_timeout(net, thd->variables.net_read_timeout); - net_set_write_timeout(net, thd->variables.net_write_timeout); + my_net_set_read_timeout(net, thd->variables.net_read_timeout); + my_net_set_write_timeout(net, thd->variables.net_write_timeout); DBUG_RETURN(0); } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index cfd610638ce..43d84740f0b 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -59,11 +59,11 @@ typedef struct my_dblock_st lock_db key. */ -static byte* lock_db_get_key(my_dblock_t *ptr, uint *length, - my_bool not_used __attribute__((unused))) +static uchar* lock_db_get_key(my_dblock_t *ptr, size_t *length, + my_bool not_used __attribute__((unused))) { *length= ptr->name_length; - return (byte*) ptr->name; + return (uchar*) ptr->name; } @@ -73,7 +73,7 @@ static byte* lock_db_get_key(my_dblock_t *ptr, uint *length, static void lock_db_free_element(void *ptr) { - my_free((gptr) ptr, MYF(0)); + my_free(ptr, MYF(0)); } @@ -98,12 +98,12 @@ static my_bool lock_db_insert(const char *dbname, uint length) safe_mutex_assert_owner(&LOCK_lock_db); if (!(opt= (my_dblock_t*) hash_search(&lock_db_cache, - (byte*) dbname, length))) + (uchar*) dbname, length))) { /* Db is not in the hash, insert it */ char *tmp_name; if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &opt, (uint) sizeof(*opt), &tmp_name, length+1, + &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1, NullS)) { error= 1; @@ -114,11 +114,8 @@ static my_bool lock_db_insert(const char *dbname, uint length) strmov(opt->name, dbname); opt->name_length= length; - if ((error= my_hash_insert(&lock_db_cache, (byte*) opt))) - { - my_free((gptr) opt, MYF(0)); - goto end; - } + if ((error= my_hash_insert(&lock_db_cache, (uchar*) opt))) + my_free(opt, MYF(0)); } end: @@ -135,8 +132,8 @@ void lock_db_delete(const char *name, uint length) my_dblock_t *opt; safe_mutex_assert_owner(&LOCK_lock_db); if ((opt= (my_dblock_t *)hash_search(&lock_db_cache, - (const byte*) name, length))) - hash_delete(&lock_db_cache, (byte*) opt); + (const uchar*) name, length))) + hash_delete(&lock_db_cache, (uchar*) opt); } @@ -158,11 +155,11 @@ typedef struct my_dbopt_st Function we use in the creation of our hash to get key. */ -static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, - my_bool not_used __attribute__((unused))) +static uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length, + my_bool not_used __attribute__((unused))) { *length= opt->name_length; - return (byte*) opt->name; + return (uchar*) opt->name; } @@ -187,7 +184,7 @@ static inline void write_to_binlog(THD *thd, char *query, uint q_len, static void free_dbopt(void *dbopt) { - my_free((gptr) dbopt, MYF(0)); + my_free((uchar*) dbopt, MYF(0)); } @@ -280,7 +277,7 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); rw_rdlock(&LOCK_dboptions); - if ((opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length))) + if ((opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length))) { create->default_table_charset= opt->charset; error= 0; @@ -312,12 +309,12 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); rw_wrlock(&LOCK_dboptions); - if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length))) + if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length))) { /* Options are not in the hash, insert them */ char *tmp_name; if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &opt, (uint) sizeof(*opt), &tmp_name, length+1, + &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1, NullS)) { error= 1; @@ -328,9 +325,9 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) strmov(opt->name, dbname); opt->name_length= length; - if ((error= my_hash_insert(&dboptions, (byte*) opt))) + if ((error= my_hash_insert(&dboptions, (uchar*) opt))) { - my_free((gptr) opt, MYF(0)); + my_free(opt, MYF(0)); goto end; } } @@ -352,9 +349,9 @@ void del_dbopt(const char *path) { my_dbopt_t *opt; rw_wrlock(&LOCK_dboptions); - if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const byte*) path, + if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const uchar*) path, strlen(path)))) - hash_delete(&dboptions, (byte*) opt); + hash_delete(&dboptions, (uchar*) opt); rw_unlock(&LOCK_dboptions); } @@ -392,7 +389,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) "\n", NullS) - buf); /* Error is written by my_write */ - if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME))) + if (!my_write(file,(uchar*) buf, length, MYF(MY_NABP+MY_WME))) error=0; my_close(file,MYF(0)); } @@ -541,6 +538,37 @@ bool load_db_opt_by_name(THD *thd, const char *db_name, } +/** + Return default database collation. + + @param thd Thread context. + @param db_name Database name. + + @return CHARSET_INFO object. The operation always return valid character + set, even if the database does not exist. +*/ + +CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) +{ + HA_CREATE_INFO db_info; + + if (thd->db != NULL && strcmp(db_name, thd->db) == 0) + return thd->db_charset; + + load_db_opt_by_name(thd, db_name, &db_info); + + /* + NOTE: even if load_db_opt_by_name() fails, + db_info.default_table_charset contains valid character set + (collation_server). We should not fail if load_db_opt_by_name() fails, + because it is valid case. If a database has been created just by + "mkdir", it does not contain db.opt file, but it is valid database. + */ + + return db_info.default_table_charset; +} + + /* Create a database @@ -754,10 +782,8 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if ((error=write_db_opt(thd, path, create_info))) goto exit; - /* - Change options if current database is being altered - TODO: Delete this code - */ + /* Change options if current database is being altered. */ + if (thd->db && !strcmp(thd->db,db)) { thd->db_charset= create_info->default_table_charset ? @@ -920,7 +946,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) TABLE_LIST *tbl; uint db_len; - if (!(query= thd->alloc(MAX_DROP_TABLE_Q_LEN))) + if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN))) goto exit; /* not much else we can do */ query_pos= query_data_start= strmov(query,"drop table "); query_end= query + MAX_DROP_TABLE_Q_LEN; @@ -1021,7 +1047,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, DBUG_PRINT("my",("New subdir found: %s", newpath)); if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0) goto err; - if (!(copy_of_path= thd->memdup(newpath, length+1)) || + if (!(copy_of_path= (char*) thd->memdup(newpath, length+1)) || !(dir= new (thd->mem_root) String(copy_of_path, length, &my_charset_bin)) || raid_dirs.push_back(dir)) @@ -1361,6 +1387,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) Security_context *sctx= thd->security_ctx; ulong db_access= sctx->db_access; + CHARSET_INFO *db_default_cl; DBUG_ENTER("mysql_change_db"); DBUG_PRINT("enter",("name: '%s'", new_db_name->str)); @@ -1448,7 +1475,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) if (!force_switch && !(db_access & DB_ACLS) && - (!grant_option || check_grant_db(thd, new_db_file_name.str))) + check_grant_db(thd, new_db_file_name.str)) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, @@ -1490,16 +1517,9 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) attributes and will be freed in THD::~THD(). */ - { - HA_CREATE_INFO db_options; - - load_db_opt_by_name(thd, new_db_name->str, &db_options); + db_default_cl= get_default_db_collation(thd, new_db_file_name.str); - mysql_change_db_impl(thd, &new_db_file_name, db_access, - db_options.default_table_charset ? - db_options.default_table_charset : - thd->variables.collation_server); - } + mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl); DBUG_RETURN(FALSE); } @@ -1511,8 +1531,8 @@ lock_databases(THD *thd, const char *db1, uint length1, { pthread_mutex_lock(&LOCK_lock_db); while (!thd->killed && - (hash_search(&lock_db_cache,(byte*) db1, length1) || - hash_search(&lock_db_cache,(byte*) db2, length2))) + (hash_search(&lock_db_cache,(uchar*) db1, length1) || + hash_search(&lock_db_cache,(uchar*) db2, length2))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); pthread_mutex_lock(&LOCK_lock_db); @@ -1654,7 +1674,7 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) table_str.length= filename_to_tablename(file->name, tname, sizeof(tname)-1); - table_str.str= sql_memdup(tname, table_str.length + 1); + table_str.str= (char*) sql_memdup(tname, table_str.length + 1); Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0); Table_ident *new_ident= new Table_ident(thd, *new_db, table_str, 0); if (!old_ident || !new_ident || diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a0bcca3e238..4fa4705062a 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -90,14 +90,26 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, Test if the user wants to delete all rows and deletion doesn't have any side-effects (because of triggers), so we can use optimized handler::delete_all_rows() method. - We implement fast TRUNCATE for InnoDB even if triggers are present. - TRUNCATE ignores triggers. + + We implement fast TRUNCATE for InnoDB even if triggers are + present. TRUNCATE ignores triggers. + + We can use delete_all_rows() if and only if: + - We allow new functions (not using option --skip-new), and are + not in safe mode (not using option --safe-mode) + - There is no limit clause + - The condition is constant + - If there is a condition, then it it produces a non-zero value + - If the current command is DELETE FROM with no where clause + (i.e., not TRUNCATE) then: + - We should not be binlogging this statement row-based, and + - there should be no delete triggers associated with the table. */ if (!using_limit && const_cond && (!conds || conds->val_int()) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && (thd->lex->sql_command == SQLCOM_TRUNCATE || - !(table->triggers && table->triggers->has_delete_triggers())) && - !thd->current_stmt_binlog_row_based) + (!thd->current_stmt_binlog_row_based && + !(table->triggers && table->triggers->has_delete_triggers())))) { /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -438,7 +450,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) { handler *file= (handler*)arg; - return file->cmp_ref((const byte*)a, (const byte*)b); + return file->cmp_ref((const uchar*)a, (const uchar*)b); } /* diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index aaca6373f37..300ec7f3c62 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -92,7 +92,7 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags); Pointer to the TABLE_LIST struct. */ -static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p, +static char *mysql_ha_hash_get_key(TABLE_LIST *tables, size_t *key_len_p, my_bool first __attribute__((unused))) { *key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */ @@ -167,7 +167,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) } else if (! reopen) /* Otherwise we have 'tables' already. */ { - if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias, + if (hash_search(&thd->handler_tables_hash, (uchar*) tables->alias, strlen(tables->alias) + 1)) { DBUG_PRINT("info",("duplicate '%s'", tables->alias)); @@ -208,10 +208,10 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) namelen= strlen(tables->table_name) + 1; aliaslen= strlen(tables->alias) + 1; if (!(my_multi_malloc(MYF(MY_WME), - &hash_tables, sizeof(*hash_tables), - &db, dblen, - &name, namelen, - &alias, aliaslen, + &hash_tables, (uint) sizeof(*hash_tables), + &db, (uint) dblen, + &name, (uint) namelen, + &alias, (uint) aliaslen, NullS))) goto err; /* structure copy */ @@ -224,7 +224,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) memcpy(hash_tables->alias, tables->alias, aliaslen); /* add to hash */ - if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables)) + if (my_hash_insert(&thd->handler_tables_hash, (uchar*) hash_tables)) { my_free((char*) hash_tables, MYF(0)); mysql_ha_close(thd, tables); @@ -270,7 +270,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) tables->db, tables->table_name, tables->alias)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (byte*) tables->alias, + (uchar*) tables->alias, strlen(tables->alias) + 1))) { /* @@ -295,7 +295,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) } VOID(pthread_mutex_unlock(&LOCK_open)); } - hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); + hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); } else { @@ -345,7 +345,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, String buffer(buff, sizeof(buff), system_charset_info); int error, keyno= -1; uint num_rows; - byte *key; + uchar *key; uint key_len; bool not_used; DBUG_ENTER("mysql_ha_read"); @@ -362,7 +362,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, it++; if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (byte*) tables->alias, + (uchar*) tables->alias, strlen(tables->alias) + 1))) { table= hash_tables->table; @@ -536,7 +536,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, keypart_map= (keypart_map << 1) | 1; } - if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len)))) + if (!(key= (uchar*) thd->calloc(ALIGN_SIZE(key_len)))) goto err; table->file->ha_index_or_rnd_end(); table->file->ha_index_init(keyno, 1); @@ -732,13 +732,13 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) table->alias, mode_flags)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (byte*) table->alias, + (uchar*) table->alias, strlen(table->alias) + 1))) { if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) { /* This is a final close. Remove from hash. */ - hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); + hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); } else { @@ -791,7 +791,7 @@ void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table) { TABLE_LIST *hash_tables; if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (byte*) table->alias, + (uchar*) table->alias, strlen(table->alias) + 1))) { /* Mark table as ready for reopen. */ diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 79d658c2a85..023bd1fec94 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -272,7 +272,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations, List<String> *names, String *name, String *description, String *example) { - char buff[8]; // Max int length + uchar buff[8]; // Max int length int count= 0; int iindex_topic, iindex_relations; Field *rtopic_id, *rkey_id; @@ -295,20 +295,20 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations, rkey_id->store((longlong) key_id, TRUE); rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW); int key_res= relations->file->index_read(relations->record[0], - (byte *) buff, (key_part_map)1, + buff, (key_part_map) 1, HA_READ_KEY_EXACT); for ( ; !key_res && key_id == (int16) rkey_id->val_int() ; key_res= relations->file->index_next(relations->record[0])) { - char topic_id_buff[8]; + uchar topic_id_buff[8]; longlong topic_id= rtopic_id->val_int(); Field *field= find_fields[help_topic_help_topic_id].field; field->store((longlong) topic_id, TRUE); field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW); - if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff, + if (!topics->file->index_read(topics->record[0], topic_id_buff, (key_part_map)1, HA_READ_KEY_EXACT)) { memorize_variant_topic(thd,topics,count,find_fields, @@ -637,7 +637,7 @@ bool mysqld_help(THD *thd, const char *mask) MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_help"); - bzero((gptr)tables,sizeof(tables)); + bzero((uchar*)tables,sizeof(tables)); tables[0].alias= tables[0].table_name= (char*) "help_topic"; tables[0].lock_type= TL_READ; tables[0].next_global= tables[0].next_local= diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a4da752feb6..c0efa621422 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -189,15 +189,12 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, return -1; } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (grant_option) - { - Field_iterator_table field_it; - field_it.set_table(table); - if (check_grant_all_columns(thd, INSERT_ACL, &table->grant, - table->s->db.str, table->s->table_name.str, - &field_it)) - return -1; - } + Field_iterator_table field_it; + field_it.set_table(table); + if (check_grant_all_columns(thd, INSERT_ACL, &table->grant, + table->s->db.str, table->s->table_name.str, + &field_it)) + return -1; #endif clear_timestamp_auto_bits(table->timestamp_field_type, TIMESTAMP_AUTO_SET_ON_INSERT); @@ -846,10 +843,36 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (mysql_bin_log.is_open()) { if (error <= 0) + { + /* + [Guilhem wrote] Temporary errors may have filled + thd->net.last_error/errno. For example if there has + been a disk full error when writing the row, and it was + MyISAM, then thd->net.last_error/errno will be set to + "disk full"... and the my_pwrite() will wait until free + space appears, and so when it finishes then the + write_row() was entirely successful + */ + /* todo: consider removing */ thd->clear_error(); + } + /* bug#22725: + + A query which per-row-loop can not be interrupted with + KILLED, like INSERT, and that does not invoke stored + routines can be binlogged with neglecting the KILLED error. + + If there was no error (error == zero) until after the end of + inserting loop the KILLED flag that appeared later can be + disregarded since previously possible invocation of stored + routines did not result in any error due to the KILLED. In + such case the flag is ignored for constructing binlog event. + */ + DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, - transactional_table, FALSE) && + transactional_table, FALSE, + (error>0) ? thd->killed : THD::NOT_KILLED) && transactional_table) { error=1; @@ -861,7 +884,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } if (transactional_table) error=ha_autocommit_or_rollback(thd,error); - + if (thd->lock) { mysql_unlock_tables(thd, thd->lock); @@ -909,20 +932,24 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || !thd->cuted_fields)) { - thd->row_count_func= info.copied+info.deleted+info.updated; + thd->row_count_func= info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); send_ok(thd, (ulong) thd->row_count_func, id); } else { char buff[160]; + ha_rows updated=((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); if (ignore) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (lock_type == TL_WRITE_DELAYED) ? (ulong) 0 : (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); else sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields); - thd->row_count_func= info.copied+info.deleted+info.updated; + (ulong) (info.deleted + updated), (ulong) thd->cuted_fields); + thd->row_count_func= info.copied + info.deleted + updated; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); } thd->abort_on_warning= 0; @@ -1357,9 +1384,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto err; } } - key_copy((byte*) key,table->record[0],table->key_info+key_nr,0); + key_copy((uchar*) key,table->record[0],table->key_info+key_nr,0); if ((error=(table->file->index_read_idx(table->record[1],key_nr, - (byte*) key, HA_WHOLE_KEY, + (uchar*) key, HA_WHOLE_KEY, HA_READ_KEY_EXACT)))) goto err; } @@ -1392,19 +1419,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto before_trg_err; table->file->restore_auto_increment(prev_insert_id); - if ((error=table->file->ha_update_row(table->record[1], - table->record[0]))) - { - if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) - { - goto ok_or_after_trg_err; - } - goto err; - } if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) || - compare_record(table)) + compare_record(table)) { + if ((error=table->file->ha_update_row(table->record[1], + table->record[0]))) + { + if (info->ignore && + !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + { + goto ok_or_after_trg_err; + } + goto err; + } + info->updated++; /* If ON DUP KEY UPDATE updates a row instead of inserting one, it's @@ -1423,6 +1451,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) info->copied++; } + if (table->next_number_field) + table->file->adjust_next_insert_id_after_explicit_value( + table->next_number_field->val_int()); + info->touched++; + goto ok_or_after_trg_err; } else /* DUP_REPLACE */ @@ -1641,6 +1674,7 @@ public: Statement-based replication of INSERT DELAYED has problems with RAND() and user vars, so in mixed mode we go to row-based. */ + thd.lex->set_stmt_unsafe(); thd.set_current_stmt_binlog_row_based_if_mixed(); bzero((char*) &thd.net, sizeof(thd.net)); // Safety @@ -1830,8 +1864,8 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) thd->proc_info="got old table"; if (tmp->thd.killed) { - if (tmp->thd.net.report_error) - { + if (tmp->thd.net.report_error) + { /* Copy the error message. Note that we don't treat fatal errors in the delayed thread as fatal errors in the @@ -1847,7 +1881,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) if (thd->killed) { tmp->unlock(); - goto end_create; + goto end_create; } } pthread_mutex_unlock(&LOCK_delayed_create); @@ -1863,7 +1897,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) } /* Unlock the delayed insert object after its last access. */ tmp->unlock(); - DBUG_RETURN(table_list->table == NULL); + DBUG_RETURN((table_list->table == NULL)); end_create: pthread_mutex_unlock(&LOCK_delayed_create); @@ -1893,7 +1927,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) Field **field,**org_field, *found_next_number_field; TABLE *copy; TABLE_SHARE *share= table->s; - byte *bitmap; + uchar *bitmap; DBUG_ENTER("Delayed_insert::get_local_table"); /* First request insert thread to get a lock */ @@ -1937,7 +1971,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) /* We don't need to change the file handler here */ /* Assign the pointers for the field pointers array and the record. */ field= copy->field= (Field**) (copy + 1); - bitmap= (byte*) (field + share->fields + 1); + bitmap= (uchar*) (field + share->fields + 1); copy->record[0]= (bitmap + share->column_bitmap_size * 2); memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength); /* @@ -2006,7 +2040,8 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, Delayed_insert *di=thd->di; const Discrete_interval *forced_auto_inc; DBUG_ENTER("write_delayed"); - DBUG_PRINT("enter", ("query = '%s' length %u", query.str, query.length)); + DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, + (ulong) query.length)); thd->proc_info="waiting for handler insert"; pthread_mutex_lock(&di->mutex); @@ -2393,7 +2428,7 @@ static void free_delayed_insert_blobs(register TABLE *table) { if ((*ptr)->flags & BLOB_FLAG) { - char *str; + uchar *str; ((Field_blob *) (*ptr))->get_ptr(&str); my_free(str,MYF(MY_ALLOW_ZERO_PTR)); ((Field_blob *) (*ptr))->reset(); @@ -2455,8 +2490,9 @@ bool Delayed_insert::handle_inserts(void) use values from the previous interval (of the previous rows). */ bool log_query= (row->log_query && row->query.str != NULL); - DBUG_PRINT("delayed", ("query: '%s' length: %u", row->query.str ? - row->query.str : "[NULL]", row->query.length)); + DBUG_PRINT("delayed", ("query: '%s' length: %lu", row->query.str ? + row->query.str : "[NULL]", + (ulong) row->query.length)); if (log_query) { /* @@ -2538,7 +2574,7 @@ bool Delayed_insert::handle_inserts(void) if (table->s->blob_fields) free_delayed_insert_blobs(table); - thread_safe_sub(delayed_rows_in_use,1,&LOCK_delayed_status); + thread_safe_decrement(delayed_rows_in_use,&LOCK_delayed_status); thread_safe_increment(delayed_insert_writes,&LOCK_delayed_status); pthread_mutex_lock(&mutex); @@ -2788,7 +2824,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) while ((item= li++)) { item->transform(&Item::update_value_transformer, - (byte*)lex->current_select); + (uchar*)lex->current_select); } } @@ -3111,7 +3147,9 @@ bool select_insert::send_eof() else sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields); - thd->row_count_func= info.copied+info.deleted+info.updated; + thd->row_count_func= info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); id= (thd->first_successful_insert_id_in_cur_stmt > 0) ? thd->first_successful_insert_id_in_cur_stmt : @@ -3138,11 +3176,11 @@ bool select_insert::send_eof() temporary table flag) create_table in Pointer to TABLE_LIST object providing database and name for table to be created or to be open - extra_fields in/out Initial list of fields for table to be created - keys in List of keys for table to be created + alter_info in/out Initial list of columns and indexes for the table + to be created items in List of items which should be used to produce rest of fields for the table (corresponding fields will - be added to the end of 'extra_fields' list) + be added to the end of alter_info->create_list) lock out Pointer to the MYSQL_LOCK object for table created (or open temporary table) will be returned in this parameter. Since this table is not included in @@ -3171,13 +3209,12 @@ bool select_insert::send_eof() static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, TABLE_LIST *create_table, - List<create_field> *extra_fields, - List<Key> *keys, + Alter_info *alter_info, List<Item> *items, MYSQL_LOCK **lock, TABLEOP_HOOKS *hooks) { - TABLE tmp_table; // Used during 'create_field()' + TABLE tmp_table; // Used during 'Create_field()' TABLE_SHARE share; TABLE *table= 0; uint select_field_count= items->elements; @@ -3221,7 +3258,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, while ((item=it++)) { - create_field *cr_field; + Create_field *cr_field; Field *field, *def_field; if (item->type() == Item::FUNC_ITEM) field= item->tmp_table_field(&tmp_table); @@ -3230,13 +3267,13 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, 0); if (!field || - !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? + !(cr_field=new Create_field(field,(item->type() == Item::FIELD_ITEM ? ((Item_field *)item)->field : (Field*) 0)))) DBUG_RETURN(0); if (item->maybe_null) cr_field->flags &= ~NOT_NULL_FLAG; - extra_fields->push_back(cr_field); + alter_info->create_list.push_back(cr_field); } DBUG_EXECUTE_IF("sleep_create_select_before_create", my_sleep(6000000);); @@ -3261,10 +3298,9 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, tmp_disable_binlog(thd); if (!mysql_create_table_no_lock(thd, create_table->db, create_table->table_name, - create_info, *extra_fields, *keys, 0, - select_field_count, 0)) + create_info, alter_info, 0, + select_field_count)) { - if (create_info->table_existed && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { @@ -3306,7 +3342,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, close_temporary_table(thd, create_table); } } - } reenable_binlog(thd); if (!table) // open failed @@ -3318,8 +3353,15 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, table->reginfo.lock_type=TL_WRITE; hooks->prelock(&table, 1); // Call prelock hooks if (! ((*lock)= mysql_lock_tables(thd, &table, 1, - MYSQL_LOCK_IGNORE_FLUSH, ¬_used))) + MYSQL_LOCK_IGNORE_FLUSH, ¬_used)) || + hooks->postlock(&table, 1)) { + if (*lock) + { + mysql_unlock_tables(thd, *lock); + *lock= 0; + } + if (!create_info->table_existed) drop_open_table(thd, table, create_table->db, create_table->table_name); DBUG_RETURN(0); @@ -3354,24 +3396,35 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) */ class MY_HOOKS : public TABLEOP_HOOKS { public: - MY_HOOKS(select_create *x) : ptr(x) { } + MY_HOOKS(select_create *x, TABLE_LIST *create_table, + TABLE_LIST *select_tables) + : ptr(x), all_tables(*create_table) + { + all_tables.next_global= select_tables; + } private: - virtual void do_prelock(TABLE **tables, uint count) + virtual int do_postlock(TABLE **tables, uint count) { + THD *thd= const_cast<THD*>(ptr->get_thd()); + if (int error= decide_logging_format(thd, &all_tables)) + return error; + TABLE const *const table = *tables; - if (ptr->get_thd()->current_stmt_binlog_row_based && + if (thd->current_stmt_binlog_row_based && !table->s->tmp_table && !ptr->get_create_info()->table_existed) { ptr->binlog_show_create_table(tables, count); } + return 0; } select_create *ptr; + TABLE_LIST all_tables; }; - MY_HOOKS hooks(this); + MY_HOOKS hooks(this, create_table, select_tables); hook_ptr= &hooks; unit= u; @@ -3388,7 +3441,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } if (!(table= create_table_from_items(thd, create_info, create_table, - extra_fields, keys, &values, + alter_info, &values, &thd->extra_lock, hook_ptr))) DBUG_RETURN(-1); // abort() deletes table diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65e5f8035e4..304feea5f5c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -31,16 +31,6 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01; -/* Macros to look like lex */ - -#define yyGet() ((uchar) *(lip->ptr++)) -#define yyGetLast() ((uchar) lip->ptr[-1]) -#define yyPeek() ((uchar) lip->ptr[0]) -#define yyPeek2() ((uchar) lip->ptr[1]) -#define yyUnget() lip->ptr-- -#define yySkip() lip->ptr++ -#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1) - /* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 @@ -127,17 +117,24 @@ Lex_input_stream::Lex_input_stream(THD *thd, yylineno(1), yytoklen(0), yylval(NULL), - ptr(buffer), - tok_start(NULL), - tok_end(NULL), - end_of_query(buffer + length), - tok_start_prev(NULL), - buf(buffer), + m_ptr(buffer), + m_tok_start(NULL), + m_tok_end(NULL), + m_end_of_query(buffer + length), + m_tok_start_prev(NULL), + m_buf(buffer), + m_echo(true), + m_cpp_tok_start(NULL), + m_cpp_tok_start_prev(NULL), + m_cpp_tok_end(NULL), next_state(MY_LEX_START), found_semicolon(NULL), ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)), - stmt_prepare_mode(FALSE) + stmt_prepare_mode(FALSE), + in_comment(NO_COMMENT) { + m_cpp_buf= (char*) thd->alloc(length + 1); + m_cpp_ptr= m_cpp_buf; } Lex_input_stream::~Lex_input_stream() @@ -192,7 +189,6 @@ void lex_start(THD *thd) lex->parsing_options.reset(); lex->empty_field_list_on_rset= 0; lex->select_lex.select_number= 1; - lex->in_comment=0; lex->length=0; lex->part_info= 0; lex->select_lex.in_sum_expr=0; @@ -261,7 +257,7 @@ void lex_end(LEX *lex) static int find_keyword(Lex_input_stream *lip, uint len, bool function) { - const char *tok= lip->tok_start; + const char *tok= lip->get_tok_start(); SYMBOL *symbol= get_hash_symbol(tok, len, function); if (symbol) @@ -312,9 +308,9 @@ bool is_lex_native_function(const LEX_STRING *name) static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length) { LEX_STRING tmp; - yyUnget(); // ptr points now after last token char + lip->yyUnget(); // ptr points now after last token char tmp.length=lip->yytoklen=length; - tmp.str= lip->m_thd->strmake(lip->tok_start + skip, tmp.length); + tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length); return tmp; } @@ -332,10 +328,10 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip, LEX_STRING tmp; const char *from, *end; char *to; - yyUnget(); // ptr points now after last token char + lip->yyUnget(); // ptr points now after last token char tmp.length= lip->yytoklen=length; tmp.str=(char*) lip->m_thd->alloc(tmp.length+1); - from= lip->tok_start + skip; + from= lip->get_tok_start() + skip; to= tmp.str; end= to+length; for ( ; to != end; ) @@ -353,23 +349,25 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip, Fix sometimes to do only one scan of the string */ -static char *get_text(Lex_input_stream *lip) +static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip) { reg1 uchar c,sep; uint found_escape=0; CHARSET_INFO *cs= lip->m_thd->charset(); - sep= yyGetLast(); // String should end with this - while (lip->ptr != lip->end_of_query) + sep= lip->yyGetLast(); // String should end with this + while (! lip->eof()) { - c = yyGet(); + c= lip->yyGet(); #ifdef USE_MB { int l; if (use_mb(cs) && - (l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) { - lip->ptr += l-1; - continue; + (l = my_ismbchar(cs, + lip->get_ptr() -1, + lip->get_end_of_query()))) { + lip->skip_binary(l-1); + continue; } } #endif @@ -377,26 +375,31 @@ static char *get_text(Lex_input_stream *lip) !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) { // Escaped character found_escape=1; - if (lip->ptr == lip->end_of_query) + if (lip->eof()) return 0; - yySkip(); + lip->yySkip(); } else if (c == sep) { - if (c == yyGet()) // Check if two separators in a row + if (c == lip->yyGet()) // Check if two separators in a row { - found_escape=1; // dupplicate. Remember for delete + found_escape=1; // duplicate. Remember for delete continue; } else - yyUnget(); + lip->yyUnget(); /* Found end. Unescape and return string */ const char *str, *end; char *start; - str=lip->tok_start+1; - end=lip->ptr-1; + str= lip->get_tok_start(); + end= lip->get_ptr(); + /* Extract the text from the token */ + str += pre_skip; + end -= post_skip; + DBUG_ASSERT(end >= str); + if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1))) return (char*) ""; // Sql_alloc has set error flag if (!found_escape) @@ -581,9 +584,7 @@ int MYSQLlex(void *arg, void *yythd) lip->yylval=yylval; // The global state - lip->tok_start_prev= lip->tok_start; - - lip->tok_start=lip->tok_end=lip->ptr; + lip->start_token(); state=lip->next_state; lip->next_state=MY_LEX_OPERATOR_OR_IDENT; LINT_INIT(c); @@ -592,17 +593,22 @@ int MYSQLlex(void *arg, void *yythd) switch (state) { case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword case MY_LEX_START: // Start of token - // Skip startspace - for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet()) + // Skip starting whitespace + while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP) { if (c == '\n') lip->yylineno++; + + lip->yySkip(); } - lip->tok_start=lip->ptr-1; // Start of real token + + /* Start of real token */ + lip->restart_token(); + c= lip->yyGet(); state= (enum my_lex_states) state_map[c]; break; case MY_LEX_ESCAPE: - if (yyGet() == 'N') + if (lip->yyGet() == 'N') { // Allow \N as shortcut for NULL yylval->lex_str.str=(char*) "\\N"; yylval->lex_str.length=2; @@ -610,40 +616,53 @@ int MYSQLlex(void *arg, void *yythd) } case MY_LEX_CHAR: // Unknown or single char token case MY_LEX_SKIP: // This should not happen - if (c == '-' && yyPeek() == '-' && - (my_isspace(cs,yyPeek2()) || - my_iscntrl(cs,yyPeek2()))) + if (c == '-' && lip->yyPeek() == '-' && + (my_isspace(cs,lip->yyPeekn(1)) || + my_iscntrl(cs,lip->yyPeekn(1)))) { state=MY_LEX_COMMENT; break; } - yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr - yylval->lex_str.length=1; - c=yyGet(); + if (c != ')') lip->next_state= MY_LEX_START; // Allow signed numbers + if (c == ',') - lip->tok_start=lip->ptr; // Let tok_start point at next item - /* - Check for a placeholder: it should not precede a possible identifier - because of binlogging: when a placeholder is replaced with - its value in a query for the binlog, the query must stay - grammatically correct. - */ - else if (c == '?' && lip->stmt_prepare_mode && !ident_map[yyPeek()]) + { + /* + Warning: + This is a work around, to make the "remember_name" rule in + sql/sql_yacc.yy work properly. + The problem is that, when parsing "select expr1, expr2", + the code generated by bison executes the *pre* action + remember_name (see select_item) *before* actually parsing the + first token of expr2. + */ + lip->restart_token(); + } + else + { + /* + Check for a placeholder: it should not precede a possible identifier + because of binlogging: when a placeholder is replaced with + its value in a query for the binlog, the query must stay + grammatically correct. + */ + if (c == '?' && lip->stmt_prepare_mode && !ident_map[lip->yyPeek()]) return(PARAM_MARKER); + } + return((int) c); case MY_LEX_IDENT_OR_NCHAR: - if (yyPeek() != '\'') - { + if (lip->yyPeek() != '\'') + { state= MY_LEX_IDENT; break; } /* Found N'string' */ - lip->tok_start++; // Skip N - yySkip(); // Skip ' - if (!(yylval->lex_str.str = get_text(lip))) + lip->yySkip(); // Skip ' + if (!(yylval->lex_str.str = get_text(lip, 2, 1))) { state= MY_LEX_CHAR; // Read char by char break; @@ -652,13 +671,13 @@ int MYSQLlex(void *arg, void *yythd) return(NCHAR_STRING); case MY_LEX_IDENT_OR_HEX: - if (yyPeek() == '\'') + if (lip->yyPeek() == '\'') { // Found x'hex-number' state= MY_LEX_HEX_NUMBER; break; } case MY_LEX_IDENT_OR_BIN: - if (yyPeek() == '\'') + if (lip->yyPeek() == '\'') { // Found b'bin-number' state= MY_LEX_BIN_NUMBER; break; @@ -669,54 +688,58 @@ int MYSQLlex(void *arg, void *yythd) if (use_mb(cs)) { result_state= IDENT_QUOTED; - if (my_mbcharlen(cs, yyGetLast()) > 1) + if (my_mbcharlen(cs, lip->yyGetLast()) > 1) { - int l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query); + int l = my_ismbchar(cs, + lip->get_ptr() -1, + lip->get_end_of_query()); if (l == 0) { state = MY_LEX_CHAR; continue; } - lip->ptr += l - 1; + lip->skip_binary(l - 1); } - while (ident_map[c=yyGet()]) + while (ident_map[c=lip->yyGet()]) { if (my_mbcharlen(cs, c) > 1) { int l; - if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0) + if ((l = my_ismbchar(cs, + lip->get_ptr() -1, + lip->get_end_of_query())) == 0) break; - lip->ptr += l-1; + lip->skip_binary(l-1); } } } else #endif { - for (result_state= c; ident_map[c= yyGet()]; result_state|= c); + for (result_state= c; ident_map[c= lip->yyGet()]; result_state|= c); /* If there were non-ASCII characters, mark that we must convert */ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; } - length= (uint) (lip->ptr - lip->tok_start)-1; - start= lip->ptr; + length= lip->yyLength(); + start= lip->get_ptr(); if (lip->ignore_space) { /* If we find a space then this can't be an identifier. We notice this below by checking start != lex->ptr. */ - for (; state_map[c] == MY_LEX_SKIP ; c= yyGet()); + for (; state_map[c] == MY_LEX_SKIP ; c= lip->yyGet()); } - if (start == lip->ptr && c == '.' && ident_map[yyPeek()]) + if (start == lip->get_ptr() && c == '.' && ident_map[lip->yyPeek()]) lip->next_state=MY_LEX_IDENT_SEP; else { // '(' must follow directly if function - yyUnget(); - if ((tokval = find_keyword(lip, length,c == '('))) + lip->yyUnget(); + if ((tokval = find_keyword(lip, length, c == '('))) { lip->next_state= MY_LEX_START; // Allow signed numbers return(tokval); // Was keyword } - yySkip(); // next state does a unget + lip->yySkip(); // next state does a unget } yylval->lex_str=get_token(lip, 0, length); @@ -735,16 +758,48 @@ int MYSQLlex(void *arg, void *yythd) return(result_state); // IDENT or IDENT_QUOTED case MY_LEX_IDENT_SEP: // Found ident and now '.' - yylval->lex_str.str=(char*) lip->ptr; - yylval->lex_str.length=1; - c=yyGet(); // should be '.' + yylval->lex_str.str= (char*) lip->get_ptr(); + yylval->lex_str.length= 1; + c= lip->yyGet(); // should be '.' lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword) - if (!ident_map[yyPeek()]) // Probably ` or " + if (!ident_map[lip->yyPeek()]) // Probably ` or " lip->next_state= MY_LEX_START; return((int) c); case MY_LEX_NUMBER_IDENT: // number or ident which num-start - while (my_isdigit(cs,(c = yyGet()))) ; + if (lip->yyGetLast() == '0') + { + c= lip->yyGet(); + if (c == 'x') + { + while (my_isxdigit(cs,(c = lip->yyGet()))) ; + if ((lip->yyLength() >= 3) && !ident_map[c]) + { + /* skip '0x' */ + yylval->lex_str=get_token(lip, 2, lip->yyLength()-2); + return (HEX_NUM); + } + lip->yyUnget(); + state= MY_LEX_IDENT_START; + break; + } + else if (c == 'b') + { + while ((c= lip->yyGet()) == '0' || c == '1'); + if ((lip->yyLength() >= 3) && !ident_map[c]) + { + /* Skip '0b' */ + yylval->lex_str= get_token(lip, 2, lip->yyLength()-2); + return (BIN_NUM); + } + lip->yyUnget(); + state= MY_LEX_IDENT_START; + break; + } + lip->yyUnget(); + } + + while (my_isdigit(cs, (c = lip->yyGet()))) ; if (!ident_map[c]) { // Can't be identifier state=MY_LEX_INT_OR_REAL; @@ -753,42 +808,18 @@ int MYSQLlex(void *arg, void *yythd) if (c == 'e' || c == 'E') { // The following test is written this way to allow numbers of type 1e1 - if (my_isdigit(cs,yyPeek()) || - (c=(yyGet())) == '+' || c == '-') + if (my_isdigit(cs,lip->yyPeek()) || + (c=(lip->yyGet())) == '+' || c == '-') { // Allow 1E+10 - if (my_isdigit(cs,yyPeek())) // Number must have digit after sign + if (my_isdigit(cs,lip->yyPeek())) // Number must have digit after sign { - yySkip(); - while (my_isdigit(cs,yyGet())) ; - yylval->lex_str=get_token(lip, 0, yyLength()); + lip->yySkip(); + while (my_isdigit(cs,lip->yyGet())) ; + yylval->lex_str=get_token(lip, 0, lip->yyLength()); return(FLOAT_NUM); } } - yyUnget(); /* purecov: inspected */ - } - else if (c == 'x' && (lip->ptr - lip->tok_start) == 2 && - lip->tok_start[0] == '0' ) - { // Varbinary - while (my_isxdigit(cs,(c = yyGet()))) ; - if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c]) - { - /* skip '0x' */ - yylval->lex_str=get_token(lip, 2, yyLength()-2); - return (HEX_NUM); - } - yyUnget(); - } - else if (c == 'b' && (lip->ptr - lip->tok_start) == 2 && - lip->tok_start[0] == '0' ) - { // b'bin-number' - while (my_isxdigit(cs,(c = yyGet()))) ; - if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c]) - { - /* Skip '0b' */ - yylval->lex_str= get_token(lip, 2, yyLength()-2); - return (BIN_NUM); - } - yyUnget(); + lip->yyUnget(); } // fall through case MY_LEX_IDENT_START: // We come here after '.' @@ -797,44 +828,46 @@ int MYSQLlex(void *arg, void *yythd) if (use_mb(cs)) { result_state= IDENT_QUOTED; - while (ident_map[c=yyGet()]) + while (ident_map[c=lip->yyGet()]) { if (my_mbcharlen(cs, c) > 1) { int l; - if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0) + if ((l = my_ismbchar(cs, + lip->get_ptr() -1, + lip->get_end_of_query())) == 0) break; - lip->ptr += l-1; + lip->skip_binary(l-1); } } } else #endif { - for (result_state=0; ident_map[c= yyGet()]; result_state|= c); + for (result_state=0; ident_map[c= lip->yyGet()]; result_state|= c); /* If there were non-ASCII characters, mark that we must convert */ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; } - if (c == '.' && ident_map[yyPeek()]) + if (c == '.' && ident_map[lip->yyPeek()]) lip->next_state=MY_LEX_IDENT_SEP;// Next is '.' - yylval->lex_str= get_token(lip, 0, yyLength()); + yylval->lex_str= get_token(lip, 0, lip->yyLength()); return(result_state); case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char { uint double_quotes= 0; char quote_char= c; // Used char - while ((c=yyGet())) + while ((c=lip->yyGet())) { int var_length; if ((var_length= my_mbcharlen(cs, c)) == 1) { if (c == quote_char) { - if (yyPeek() != quote_char) + if (lip->yyPeek() != quote_char) break; - c=yyGet(); + c=lip->yyGet(); double_quotes++; continue; } @@ -842,78 +875,78 @@ int MYSQLlex(void *arg, void *yythd) #ifdef USE_MB else if (var_length < 1) break; // Error - lip->ptr+= var_length-1; + lip->skip_binary(var_length-1); #endif } if (double_quotes) yylval->lex_str=get_quoted_token(lip, 1, - yyLength() - double_quotes -1, + lip->yyLength() - double_quotes -1, quote_char); else - yylval->lex_str=get_token(lip, 1, yyLength() -1); + yylval->lex_str=get_token(lip, 1, lip->yyLength() -1); if (c == quote_char) - yySkip(); // Skip end ` + lip->yySkip(); // Skip end ` lip->next_state= MY_LEX_START; return(IDENT_QUOTED); } case MY_LEX_INT_OR_REAL: // Complete int or incomplete real if (c != '.') { // Found complete integer number. - yylval->lex_str=get_token(lip, 0, yyLength()); + yylval->lex_str=get_token(lip, 0, lip->yyLength()); return int_token(yylval->lex_str.str,yylval->lex_str.length); } // fall through case MY_LEX_REAL: // Incomplete real number - while (my_isdigit(cs,c = yyGet())) ; + while (my_isdigit(cs,c = lip->yyGet())) ; if (c == 'e' || c == 'E') { - c = yyGet(); + c = lip->yyGet(); if (c == '-' || c == '+') - c = yyGet(); // Skip sign + c = lip->yyGet(); // Skip sign if (!my_isdigit(cs,c)) { // No digit after sign state= MY_LEX_CHAR; break; } - while (my_isdigit(cs,yyGet())) ; - yylval->lex_str=get_token(lip, 0, yyLength()); + while (my_isdigit(cs,lip->yyGet())) ; + yylval->lex_str=get_token(lip, 0, lip->yyLength()); return(FLOAT_NUM); } - yylval->lex_str=get_token(lip, 0, yyLength()); + yylval->lex_str=get_token(lip, 0, lip->yyLength()); return(DECIMAL_NUM); case MY_LEX_HEX_NUMBER: // Found x'hexstring' - yyGet(); // Skip ' - while (my_isxdigit(cs,(c = yyGet()))) ; - length=(lip->ptr - lip->tok_start); // Length of hexnum+3 - if (!(length & 1) || c != '\'') - { - return(ABORT_SYM); // Illegal hex constant - } - yyGet(); // get_token makes an unget + lip->yySkip(); // Accept opening ' + while (my_isxdigit(cs, (c= lip->yyGet()))) ; + if (c != '\'') + return(ABORT_SYM); // Illegal hex constant + lip->yySkip(); // Accept closing ' + length= lip->yyLength(); // Length of hexnum+3 + if ((length % 2) == 0) + return(ABORT_SYM); // odd number of hex digits yylval->lex_str=get_token(lip, 2, // skip x' length-3); // don't count x' and last ' return (HEX_NUM); case MY_LEX_BIN_NUMBER: // Found b'bin-string' - yyGet(); // Skip ' - while ((c= yyGet()) == '0' || c == '1'); - length= (lip->ptr - lip->tok_start); // Length of bin-num + 3 + lip->yySkip(); // Accept opening ' + while ((c= lip->yyGet()) == '0' || c == '1'); if (c != '\'') - return(ABORT_SYM); // Illegal hex constant - yyGet(); // get_token makes an unget + return(ABORT_SYM); // Illegal hex constant + lip->yySkip(); // Accept closing ' + length= lip->yyLength(); // Length of bin-num + 3 yylval->lex_str= get_token(lip, 2, // skip b' length-3); // don't count b' and last ' return (BIN_NUM); case MY_LEX_CMP_OP: // Incomplete comparison operator - if (state_map[yyPeek()] == MY_LEX_CMP_OP || - state_map[yyPeek()] == MY_LEX_LONG_CMP_OP) - yySkip(); - if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0))) + if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP || + state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP) + lip->yySkip(); + if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0))) { lip->next_state= MY_LEX_START; // Allow signed numbers return(tokval); @@ -922,14 +955,14 @@ int MYSQLlex(void *arg, void *yythd) break; case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator - if (state_map[yyPeek()] == MY_LEX_CMP_OP || - state_map[yyPeek()] == MY_LEX_LONG_CMP_OP) + if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP || + state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP) { - yySkip(); - if (state_map[yyPeek()] == MY_LEX_CMP_OP) - yySkip(); + lip->yySkip(); + if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP) + lip->yySkip(); } - if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0))) + if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0))) { lip->next_state= MY_LEX_START; // Found long op return(tokval); @@ -938,12 +971,12 @@ int MYSQLlex(void *arg, void *yythd) break; case MY_LEX_BOOL: - if (c != yyPeek()) + if (c != lip->yyPeek()) { state=MY_LEX_CHAR; break; } - yySkip(); + lip->yySkip(); tokval = find_keyword(lip,2,0); // Is a bool operator lip->next_state= MY_LEX_START; // Allow signed numbers return(tokval); @@ -956,7 +989,7 @@ int MYSQLlex(void *arg, void *yythd) } /* " used for strings */ case MY_LEX_STRING: // Incomplete text string - if (!(yylval->lex_str.str = get_text(lip))) + if (!(yylval->lex_str.str = get_text(lip, 1, 1))) { state= MY_LEX_CHAR; // Read char by char break; @@ -966,82 +999,138 @@ int MYSQLlex(void *arg, void *yythd) case MY_LEX_COMMENT: // Comment lex->select_lex.options|= OPTION_FOUND_COMMENT; - while ((c = yyGet()) != '\n' && c) ; - yyUnget(); // Safety against eof + while ((c = lip->yyGet()) != '\n' && c) ; + lip->yyUnget(); // Safety against eof state = MY_LEX_START; // Try again break; case MY_LEX_LONG_COMMENT: /* Long C comment? */ - if (yyPeek() != '*') + if (lip->yyPeek() != '*') { state=MY_LEX_CHAR; // Probable division break; } - yySkip(); // Skip '*' lex->select_lex.options|= OPTION_FOUND_COMMENT; - if (yyPeek() == '!') // MySQL command in comment + /* Reject '/' '*', since we might need to turn off the echo */ + lip->yyUnget(); + + if (lip->yyPeekn(2) == '!') { - ulong version=MYSQL_VERSION_ID; - yySkip(); - state=MY_LEX_START; - if (my_isdigit(cs,yyPeek())) - { // Version number - version=strtol((char*) lip->ptr,(char**) &lip->ptr,10); - } - if (version <= MYSQL_VERSION_ID) - { - lex->in_comment=1; - break; - } + lip->in_comment= DISCARD_COMMENT; + /* Accept '/' '*' '!', but do not keep this marker. */ + lip->set_echo(false); + lip->yySkip(); + lip->yySkip(); + lip->yySkip(); + + /* + The special comment format is very strict: + '/' '*' '!', followed by exactly + 2 digits (major), then 3 digits (minor). + */ + char version_str[6]; + version_str[0]= lip->yyPeekn(0); + version_str[1]= lip->yyPeekn(1); + version_str[2]= lip->yyPeekn(2); + version_str[3]= lip->yyPeekn(3); + version_str[4]= lip->yyPeekn(4); + version_str[5]= 0; + if ( my_isdigit(cs, version_str[0]) + && my_isdigit(cs, version_str[1]) + && my_isdigit(cs, version_str[2]) + && my_isdigit(cs, version_str[3]) + && my_isdigit(cs, version_str[4]) + ) + { + ulong version; + version=strtol(version_str, NULL, 10); + + /* Accept 'M' 'M' 'm' 'm' 'm' */ + lip->yySkipn(5); + + if (version <= MYSQL_VERSION_ID) + { + /* Expand the content of the special comment as real code */ + lip->set_echo(true); + state=MY_LEX_START; + break; + } + } + else + { + state=MY_LEX_START; + lip->set_echo(true); + break; + } } - while (lip->ptr != lip->end_of_query && - ((c=yyGet()) != '*' || yyPeek() != '/')) + else { - if (c == '\n') - lip->yylineno++; + lip->in_comment= PRESERVE_COMMENT; + lip->yySkip(); // Accept / + lip->yySkip(); // Accept * } - if (lip->ptr != lip->end_of_query) - yySkip(); // remove last '/' - state = MY_LEX_START; // Try again + + while (! lip->eof() && + ((c=lip->yyGet()) != '*' || lip->yyPeek() != '/')) + { + if (c == '\n') + lip->yylineno++; + } + if (! lip->eof()) + lip->yySkip(); // remove last '/' + state = MY_LEX_START; // Try again + lip->set_echo(true); break; case MY_LEX_END_LONG_COMMENT: - if (lex->in_comment && yyPeek() == '/') + if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') { - yySkip(); - lex->in_comment=0; - state=MY_LEX_START; + /* Reject '*' '/' */ + lip->yyUnget(); + /* Accept '*' '/', with the proper echo */ + lip->set_echo(lip->in_comment == PRESERVE_COMMENT); + lip->yySkipn(2); + /* And start recording the tokens again */ + lip->set_echo(true); + lip->in_comment=NO_COMMENT; + state=MY_LEX_START; } else state=MY_LEX_CHAR; // Return '*' break; case MY_LEX_SET_VAR: // Check if ':=' - if (yyPeek() != '=') + if (lip->yyPeek() != '=') { state=MY_LEX_CHAR; // Return ':' break; } - yySkip(); + lip->yySkip(); return (SET_VAR); case MY_LEX_SEMICOLON: // optional line terminator - if (yyPeek()) + if (lip->yyPeek()) { if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) && !lip->stmt_prepare_mode) { lex->safe_to_cache_query= 0; - lip->found_semicolon= lip->ptr; + lip->found_semicolon= lip->get_ptr(); thd->server_status|= SERVER_MORE_RESULTS_EXISTS; lip->next_state= MY_LEX_END; + lip->set_echo(true); return (END_OF_INPUT); } state= MY_LEX_CHAR; // Return ';' break; } - /* fall true */ + lip->next_state=MY_LEX_END; // Mark for next loop + return(END_OF_INPUT); case MY_LEX_EOL: - if (lip->ptr >= lip->end_of_query) + if (lip->eof()) { - lip->next_state=MY_LEX_END; // Mark for next loop - return(END_OF_INPUT); + lip->yyUnget(); // Reject the last '\0' + lip->set_echo(false); + lip->yySkip(); + lip->set_echo(true); + lip->next_state=MY_LEX_END; // Mark for next loop + return(END_OF_INPUT); } state=MY_LEX_CHAR; break; @@ -1051,16 +1140,16 @@ int MYSQLlex(void *arg, void *yythd) /* Actually real shouldn't start with . but allow them anyhow */ case MY_LEX_REAL_OR_POINT: - if (my_isdigit(cs,yyPeek())) + if (my_isdigit(cs,lip->yyPeek())) state = MY_LEX_REAL; // Real else { state= MY_LEX_IDENT_SEP; // return '.' - yyUnget(); // Put back '.' + lip->yyUnget(); // Put back '.' } break; case MY_LEX_USER_END: // end '@' of user@hostname - switch (state_map[yyPeek()]) { + switch (state_map[lip->yyPeek()]) { case MY_LEX_STRING: case MY_LEX_USER_VARIABLE_DELIMITER: case MY_LEX_STRING_OR_DELIMITER: @@ -1072,20 +1161,20 @@ int MYSQLlex(void *arg, void *yythd) lip->next_state=MY_LEX_HOSTNAME; break; } - yylval->lex_str.str=(char*) lip->ptr; + yylval->lex_str.str=(char*) lip->get_ptr(); yylval->lex_str.length=1; return((int) '@'); case MY_LEX_HOSTNAME: // end '@' of user@hostname - for (c=yyGet() ; + for (c=lip->yyGet() ; my_isalnum(cs,c) || c == '.' || c == '_' || c == '$'; - c= yyGet()) ; - yylval->lex_str=get_token(lip, 0, yyLength()); + c= lip->yyGet()) ; + yylval->lex_str=get_token(lip, 0, lip->yyLength()); return(LEX_HOSTNAME); case MY_LEX_SYSTEM_VAR: - yylval->lex_str.str=(char*) lip->ptr; + yylval->lex_str.str=(char*) lip->get_ptr(); yylval->lex_str.length=1; - yySkip(); // Skip '@' - lip->next_state= (state_map[yyPeek()] == + lip->yySkip(); // Skip '@' + lip->next_state= (state_map[lip->yyPeek()] == MY_LEX_USER_VARIABLE_DELIMITER ? MY_LEX_OPERATOR_OR_IDENT : MY_LEX_IDENT_OR_KEYWORD); @@ -1096,19 +1185,19 @@ int MYSQLlex(void *arg, void *yythd) We should now be able to handle: [(global | local | session) .]variable_name */ - - for (result_state= 0; ident_map[c= yyGet()]; result_state|= c); + + for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c); /* If there were non-ASCII characters, mark that we must convert */ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; - + if (c == '.') lip->next_state=MY_LEX_IDENT_SEP; - length= (uint) (lip->ptr - lip->tok_start)-1; - if (length == 0) + length= lip->yyLength(); + if (length == 0) return(ABORT_SYM); // Names must be nonempty. if ((tokval= find_keyword(lip, length,0))) { - yyUnget(); // Put back 'c' + lip->yyUnget(); // Put back 'c' return(tokval); // Was keyword } yylval->lex_str=get_token(lip, 0, length); @@ -1118,29 +1207,62 @@ int MYSQLlex(void *arg, void *yythd) } -/* - Skip comment in the end of statement. +Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root) + :drop_list(rhs.drop_list, mem_root), + alter_list(rhs.alter_list, mem_root), + key_list(rhs.key_list, mem_root), + create_list(rhs.create_list, mem_root), + flags(rhs.flags), + keys_onoff(rhs.keys_onoff), + tablespace_op(rhs.tablespace_op), + partition_names(rhs.partition_names, mem_root), + no_parts(rhs.no_parts), + change_level(rhs.change_level), + datetime_field(rhs.datetime_field), + error_if_not_empty(rhs.error_if_not_empty) +{ + /* + Make deep copies of used objects. + This is not a fully deep copy - clone() implementations + of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec + do not copy string constants. At the same length the only + reason we make a copy currently is that ALTER/CREATE TABLE + code changes input Alter_info definitions, but string + constants never change. + */ + list_copy_and_replace_each_value(drop_list, mem_root); + list_copy_and_replace_each_value(alter_list, mem_root); + list_copy_and_replace_each_value(key_list, mem_root); + list_copy_and_replace_each_value(create_list, mem_root); + /* partition_names are not deeply copied currently */ +} - SYNOPSIS - skip_rear_comments() - begin pointer to the beginning of statement - end pointer to the end of statement - DESCRIPTION - The function is intended to trim comments at the end of the statement. +void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str) +{ + /* + TODO: + This code assumes that there are no multi-bytes characters + that can be considered white-space. + */ - RETURN - Pointer to the last non-comment symbol of the statement. -*/ + while ((str->length > 0) && (my_isspace(cs, str->str[0]))) + { + str->length --; + str->str ++; + } -const char *skip_rear_comments(const char *begin, const char *end) -{ - while (begin < end && (end[-1] <= ' ' || end[-1] == '*' || - end[-1] == '/' || end[-1] == ';')) - end-= 1; - return end; + /* + FIXME: + Also, parsing backward is not safe with multi bytes characters + */ + while ((str->length > 0) && (my_isspace(cs, str->str[str->length-1]))) + { + str->length --; + } } + /* st_select_lex structures initialisations */ @@ -1235,7 +1357,7 @@ void st_select_lex::init_select() linkage= UNSPECIFIED_TYPE; order_list.elements= 0; order_list.first= 0; - order_list.next= (byte**) &order_list.first; + order_list.next= (uchar**) &order_list.first; /* Set limit and offset to default values */ select_limit= 0; /* denotes the default limit = HA_POS_ERROR */ offset_limit= 0; /* denotes the default offset = 0 */ @@ -1751,7 +1873,7 @@ void Query_tables_list::reset_query_tables_list(bool init) sroutines_list.empty(); sroutines_list_own_last= sroutines_list.next; sroutines_list_own_elements= 0; - binlog_row_based_if_mixed= FALSE; + binlog_stmt_flags= 0; } @@ -1786,8 +1908,6 @@ st_lex::st_lex() :result(0), yacc_yyss(0), yacc_yyvs(0), sql_command(SQLCOM_END), option_type(OPT_DEFAULT) { - /* Check that plugins_static_buffer is declared immediately after plugins */ - compile_time_assert((&plugins + 1) == (DYNAMIC_ARRAY*)plugins_static_buffer); my_init_dynamic_array2(&plugins, sizeof(plugin_ref), plugins_static_buffer, @@ -2059,7 +2179,7 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local) { select_lex.context.table_list= select_lex.context.first_name_resolution_table= first->next_local; - select_lex.table_list.first= (byte*) (first->next_local); + select_lex.table_list.first= (uchar*) (first->next_local); select_lex.table_list.elements--; //safety first->next_local= 0; /* @@ -2140,7 +2260,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first, { first->next_local= (TABLE_LIST*) select_lex.table_list.first; select_lex.context.table_list= first; - select_lex.table_list.first= (byte*) first; + select_lex.table_list.first= (uchar*) first; select_lex.table_list.elements++; //safety } } @@ -2381,3 +2501,22 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) current_index_hint_clause, str, length)); } + +/** + A routine used by the parser to decide whether we are specifying a full + partitioning or if only partitions to add or to split. + + @note This needs to be outside of WITH_PARTITION_STORAGE_ENGINE since it + is used from the sql parser that doesn't have any #ifdef's + + @retval TRUE Yes, it is part of a management partition command + @retval FALSE No, not a management partition command +*/ + +bool st_lex::is_partition_management() const +{ + return (sql_command == SQLCOM_ALTER_TABLE && + (alter_info.flags == ALTER_ADD_PARTITION || + alter_info.flags == ALTER_REORGANIZE_PARTITION)); +} + diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3dca1d15b88..7a47c57a722 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -221,7 +221,7 @@ enum tablespace_op_type Keep in sync with index_hint_type. */ extern const char * index_hint_type_name[]; -typedef byte index_clause_map; +typedef uchar index_clause_map; /* Bits in index_clause_map : one for each possible FOR clause in @@ -409,7 +409,7 @@ public: static void *operator new(size_t size) { - return (void*) sql_alloc((uint) size); + return sql_alloc(size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } @@ -733,7 +733,7 @@ public: { order_list.elements= 0; order_list.first= 0; - order_list.next= (byte**) &order_list.first; + order_list.next= (uchar**) &order_list.first; } /* This method created for reiniting LEX in mysql_admin_table() and can be @@ -830,26 +830,77 @@ inline bool st_select_lex_unit::is_union () #define ALTER_REMOVE_PARTITIONING (1L << 25) #define ALTER_FOREIGN_KEY (1L << 26) -typedef struct st_alter_info +enum enum_alter_table_change_level { - List<Alter_drop> drop_list; - List<Alter_column> alter_list; - uint flags; - enum enum_enable_or_disable keys_onoff; - enum tablespace_op_type tablespace_op; - List<char> partition_names; - uint no_parts; - - st_alter_info(){clear();} - void clear() + ALTER_TABLE_METADATA_ONLY= 0, + ALTER_TABLE_DATA_CHANGED= 1, + ALTER_TABLE_INDEX_CHANGED= 2 +}; + +/** + @brief Parsing data for CREATE or ALTER TABLE. + + This structure contains a list of columns or indexes to be created, + altered or dropped. +*/ + +class Alter_info +{ +public: + List<Alter_drop> drop_list; + List<Alter_column> alter_list; + List<Key> key_list; + List<Create_field> create_list; + uint flags; + enum enum_enable_or_disable keys_onoff; + enum tablespace_op_type tablespace_op; + List<char> partition_names; + uint no_parts; + enum_alter_table_change_level change_level; + Create_field *datetime_field; + bool error_if_not_empty; + + + Alter_info() : + flags(0), + keys_onoff(LEAVE_AS_IS), + tablespace_op(NO_TABLESPACE_OP), + no_parts(0), + change_level(ALTER_TABLE_METADATA_ONLY), + datetime_field(NULL), + error_if_not_empty(FALSE) + {} + + void reset() { + drop_list.empty(); + alter_list.empty(); + key_list.empty(); + create_list.empty(); + flags= 0; keys_onoff= LEAVE_AS_IS; tablespace_op= NO_TABLESPACE_OP; no_parts= 0; partition_names.empty(); + change_level= ALTER_TABLE_METADATA_ONLY; + datetime_field= 0; + error_if_not_empty= FALSE; } - void reset(){drop_list.empty();alter_list.empty();clear();} -} ALTER_INFO; + /** + Construct a copy of this object to be used for mysql_alter_table + and mysql_create_table. Historically, these two functions modify + their Alter_info arguments. This behaviour breaks re-execution of + prepared statements and stored procedures and is compensated by + always supplying a copy of Alter_info to these functions. + + @return You need to use check the error in THD for out + of memory condition after calling this function. + */ + Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root); +private: + Alter_info &operator=(const Alter_info &rhs); // not implemented + Alter_info(const Alter_info &rhs); // not implemented +}; struct st_sp_chistics { @@ -913,18 +964,10 @@ public: in which it was right after query parsing. */ SQL_LIST sroutines_list; - byte **sroutines_list_own_last; + uchar **sroutines_list_own_last; uint sroutines_list_own_elements; /* - Tells if the parsing stage detected that some items require row-based - binlogging to give a reliable binlog/replication, or if we will use - stored functions or triggers which themselves need require row-based - binlogging. - */ - bool binlog_row_based_if_mixed; - - /* These constructor and destructor serve for creation/destruction of Query_tables_list instances which are used as backup storage. */ @@ -971,12 +1014,48 @@ public: query_tables_own_last= 0; } } + + /** + Has the parser/scanner detected that this statement is unsafe? + */ + inline bool is_stmt_unsafe() const { + return binlog_stmt_flags & (1U << BINLOG_STMT_FLAG_UNSAFE); + } + + /** + Flag the current (top-level) statement as unsafe. + + The flag will be reset after the statement has finished. + + */ + inline void set_stmt_unsafe() { + binlog_stmt_flags|= (1U << BINLOG_STMT_FLAG_UNSAFE); + } + + inline void clear_stmt_unsafe() { + binlog_stmt_flags&= ~(1U << BINLOG_STMT_FLAG_UNSAFE); + } + /** true if the parsed tree contains references to stored procedures or functions, false otherwise */ bool uses_stored_routines() const { return sroutines_list.elements != 0; } + +private: + enum enum_binlog_stmt_flag { + BINLOG_STMT_FLAG_UNSAFE, + BINLOG_STMT_FLAG_COUNT + }; + + /* + Tells if the parsing stage detected properties of the statement, + for example: that some items require row-based binlogging to give + a reliable binlog/replication, or if we will use stored functions + or triggers which themselves need require row-based binlogging. + */ + uint32 binlog_stmt_flags; }; @@ -998,8 +1077,40 @@ struct st_parsing_options /** + The state of the lexical parser, when parsing comments. +*/ +enum enum_comment_state +{ + /** + Not parsing comments. + */ + NO_COMMENT, + /** + Parsing comments that need to be preserved. + Typically, these are user comments '/' '*' ... '*' '/'. + */ + PRESERVE_COMMENT, + /** + Parsing comments that need to be discarded. + Typically, these are special comments '/' '*' '!' ... '*' '/', + or '/' '*' '!' 'M' 'M' 'm' 'm' 'm' ... '*' '/', where the comment + markers should not be expanded. + */ + DISCARD_COMMENT +}; + + +/** This class represents the character input stream consumed during lexical analysis. + In addition to consuming the input stream, this class performs some + comment pre processing, by filtering out out of bound special text + from the query input stream. + Two buffers, with pointers inside each buffers, are maintained in + parallel. The 'raw' buffer is the original query text, which may + contain out-of-bound comments. The 'cpp' (for comments pre processor) + is the pre-processed buffer that contains only the query text that + should be seen once out-of-bound data is removed. */ class Lex_input_stream { @@ -1007,6 +1118,218 @@ public: Lex_input_stream(THD *thd, const char* buff, unsigned int length); ~Lex_input_stream(); + /** + Set the echo mode. + When echo is true, characters parsed from the raw input stream are + preserved. When false, characters parsed are silently ignored. + @param echo the echo mode. + */ + void set_echo(bool echo) + { + m_echo= echo; + } + + /** + Skip binary from the input stream. + @param n number of bytes to accept. + */ + void skip_binary(int n) + { + if (m_echo) + { + memcpy(m_cpp_ptr, m_ptr, n); + m_cpp_ptr += n; + } + m_ptr += n; + } + + /** + Get a character, and advance in the stream. + @return the next character to parse. + */ + char yyGet() + { + char c= *m_ptr++; + if (m_echo) + *m_cpp_ptr++ = c; + return c; + } + + /** + Get the last character accepted. + @return the last character accepted. + */ + char yyGetLast() + { + return m_ptr[-1]; + } + + /** + Look at the next character to parse, but do not accept it. + */ + char yyPeek() + { + return m_ptr[0]; + } + + /** + Look ahead at some character to parse. + @param n offset of the character to look up + */ + char yyPeekn(int n) + { + return m_ptr[n]; + } + + /** + Cancel the effect of the last yyGet() or yySkip(). + Note that the echo mode should not change between calls to yyGet / yySkip + and yyUnget. The caller is responsible for ensuring that. + */ + void yyUnget() + { + m_ptr--; + if (m_echo) + m_cpp_ptr--; + } + + /** + Accept a character, by advancing the input stream. + */ + void yySkip() + { + if (m_echo) + *m_cpp_ptr++ = *m_ptr++; + else + m_ptr++; + } + + /** + Accept multiple characters at once. + @param n the number of characters to accept. + */ + void yySkipn(int n) + { + if (m_echo) + { + memcpy(m_cpp_ptr, m_ptr, n); + m_cpp_ptr += n; + } + m_ptr += n; + } + + /** + End of file indicator for the query text to parse. + @return true if there are no more characters to parse + */ + bool eof() + { + return (m_ptr >= m_end_of_query); + } + + /** + End of file indicator for the query text to parse. + @param n number of characters expected + @return true if there are less than n characters to parse + */ + bool eof(int n) + { + return ((m_ptr + n) >= m_end_of_query); + } + + /** Get the raw query buffer. */ + const char* get_buf() + { + return m_buf; + } + + /** Get the pre-processed query buffer. */ + const char* get_cpp_buf() + { + return m_cpp_buf; + } + + /** Get the end of the raw query buffer. */ + const char* get_end_of_query() + { + return m_end_of_query; + } + + /** Mark the stream position as the start of a new token. */ + void start_token() + { + m_tok_start_prev= m_tok_start; + m_tok_start= m_ptr; + m_tok_end= m_ptr; + + m_cpp_tok_start_prev= m_cpp_tok_start; + m_cpp_tok_start= m_cpp_ptr; + m_cpp_tok_end= m_cpp_ptr; + } + + /** + Adjust the starting position of the current token. + This is used to compensate for starting whitespace. + */ + void restart_token() + { + m_tok_start= m_ptr; + m_cpp_tok_start= m_cpp_ptr; + } + + /** Get the token start position, in the raw buffer. */ + const char* get_tok_start() + { + return m_tok_start; + } + + /** Get the token start position, in the pre-processed buffer. */ + const char* get_cpp_tok_start() + { + return m_cpp_tok_start; + } + + /** Get the token end position, in the raw buffer. */ + const char* get_tok_end() + { + return m_tok_end; + } + + /** Get the token end position, in the pre-processed buffer. */ + const char* get_cpp_tok_end() + { + return m_cpp_tok_end; + } + + /** Get the previous token start position, in the raw buffer. */ + const char* get_tok_start_prev() + { + return m_tok_start_prev; + } + + /** Get the current stream pointer, in the raw buffer. */ + const char* get_ptr() + { + return m_ptr; + } + + /** Get the current stream pointer, in the pre-processed buffer. */ + const char* get_cpp_ptr() + { + return m_cpp_ptr; + } + + /** Get the length of the current token, in the raw buffer. */ + uint yyLength() + { + /* + The assumption is that the lexical analyser is always 1 character ahead, + which the -1 account for. + */ + DBUG_ASSERT(m_ptr > m_tok_start); + return (uint) ((m_ptr - m_tok_start) - 1); + } + /** Current thread. */ THD *m_thd; @@ -1019,37 +1342,74 @@ public: /** Interface with bison, value of the last token parsed. */ LEX_YYSTYPE yylval; - /** Pointer to the current position in the input stream. */ - const char* ptr; +private: + /** Pointer to the current position in the raw input stream. */ + const char* m_ptr; + + /** Starting position of the last token parsed, in the raw buffer. */ + const char* m_tok_start; + + /** Ending position of the previous token parsed, in the raw buffer. */ + const char* m_tok_end; + + /** End of the query text in the input stream, in the raw buffer. */ + const char* m_end_of_query; + + /** Starting position of the previous token parsed, in the raw buffer. */ + const char* m_tok_start_prev; + + /** Begining of the query text in the input stream, in the raw buffer. */ + const char* m_buf; - /** Starting position of the last token parsed. */ - const char* tok_start; + /** Echo the parsed stream to the pre-processed buffer. */ + bool m_echo; - /** Ending position of the last token parsed. */ - const char* tok_end; + /** Pre-processed buffer. */ + char* m_cpp_buf; - /** End of the query text in the input stream. */ - const char* end_of_query; + /** Pointer to the current position in the pre-processed input stream. */ + char* m_cpp_ptr; - /** Starting position of the previous token parsed. */ - const char* tok_start_prev; + /** + Starting position of the last token parsed, + in the pre-processed buffer. + */ + const char* m_cpp_tok_start; - /** Begining of the query text in the input stream. */ - const char* buf; + /** + Starting position of the previous token parsed, + in the pre-procedded buffer. + */ + const char* m_cpp_tok_start_prev; + + /** + Ending position of the previous token parsed, + in the pre-processed buffer. + */ + const char* m_cpp_tok_end; + +public: /** Current state of the lexical analyser. */ enum my_lex_states next_state; - /** Position of ';' in the stream, to delimit multiple queries. */ + /** + Position of ';' in the stream, to delimit multiple queries. + This delimiter is in the raw buffer. + */ const char* found_semicolon; /** SQL_MODE = IGNORE_SPACE. */ bool ignore_space; - /* + + /** TRUE if we're parsing a prepared statement: in this mode we should allow placeholders and disallow multi-statements. */ bool stmt_prepare_mode; + + /** State of the lexical analyser for comments. */ + enum_comment_state in_comment; }; @@ -1066,7 +1426,6 @@ typedef struct st_lex : public Query_tables_list char *length,*dec,*change; LEX_STRING name; - Table_ident *like_name; char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ char* to_log; /* For PURGE MASTER LOGS TO */ @@ -1078,7 +1437,7 @@ typedef struct st_lex : public Query_tables_list LEX_STRING comment, ident; LEX_USER *grant_user; XID *xid; - gptr yacc_yyss,yacc_yyvs; + uchar* yacc_yyss, *yacc_yyvs; THD *thd; /* maintain a list of used plugins for this LEX */ @@ -1088,8 +1447,17 @@ typedef struct st_lex : public Query_tables_list CHARSET_INFO *charset, *underscore_charset; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; - /* Position (first character index) of SELECT of CREATE VIEW statement */ - uint create_view_select_start; + + /** Start of SELECT of CREATE VIEW statement */ + const char* create_view_select_start; + /** End of SELECT of CREATE VIEW statement */ + const char* create_view_select_end; + + /** Start of 'ON <table>', in trigger statements. */ + const char* raw_trg_on_table_name_begin; + /** End of 'ON <table>', in trigger statements. */ + const char* raw_trg_on_table_name_end; + /* Partition info structure filled in by PARTITION BY parse part */ partition_info *part_info; @@ -1099,13 +1467,11 @@ typedef struct st_lex : public Query_tables_list */ LEX_USER *definer; - List<key_part_spec> col_list; - List<key_part_spec> ref_list; + List<Key_part_spec> col_list; + List<Key_part_spec> ref_list; List<String> interval_list; List<LEX_USER> users_list; List<LEX_COLUMN> columns; - List<Key> key_list; - List<create_field> create_list; List<Item> *insert_list,field_list,value_list,update_list; List<List_item> many_values; List<set_var_base> var_list; @@ -1128,7 +1494,7 @@ typedef struct st_lex : public Query_tables_list List<LEX_STRING> db_list; SQL_LIST proc_list, auxiliary_table_list, save_list; - create_field *last_field; + Create_field *last_field; Item_sum *in_sum_func; udf_func udf; HA_CHECK_OPT check_opt; // check/repair options @@ -1190,7 +1556,9 @@ typedef struct st_lex : public Query_tables_list uint8 create_view_algorithm; uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; - bool in_comment, verbose, no_write_to_binlog; + + bool verbose, no_write_to_binlog; + bool tx_chain, tx_release; /* Special JOIN::prepare mode: changing of query is prohibited. @@ -1203,7 +1571,7 @@ typedef struct st_lex : public Query_tables_list bool safe_to_cache_query; bool subqueries, ignore; st_parsing_options parsing_options; - ALTER_INFO alter_info; + Alter_info alter_info; /* Prepared statements SQL syntax:*/ LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */ /* @@ -1254,10 +1622,12 @@ typedef struct st_lex : public Query_tables_list - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); This pointer is required to add possibly omitted DEFINER-clause to the - DDL-statement before dumping it to the binlog. + DDL-statement before dumping it to the binlog. */ const char *stmt_definition_begin; + const char *stmt_definition_end; + /* Pointers to part of LOAD DATA statement that should be rewritten during replication ("LOCAL 'filename' REPLACE INTO" part). @@ -1362,13 +1732,14 @@ typedef struct st_lex : public Query_tables_list void restore_backup_query_tables_list(Query_tables_list *backup); bool table_or_sp_used(); + bool is_partition_management() const; } LEX; struct st_lex_local: public st_lex { static void *operator new(size_t size) { - return (void*) sql_alloc((uint) size); + return sql_alloc(size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { @@ -1385,7 +1756,8 @@ extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); -extern const char *skip_rear_comments(const char *ubegin, const char *uend); + +extern void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str); extern bool is_lex_native_function(const LEX_STRING *name); diff --git a/sql/sql_list.cc b/sql/sql_list.cc index 01ab9b91424..49b649133d0 100644 --- a/sql/sql_list.cc +++ b/sql/sql_list.cc @@ -36,3 +36,37 @@ void free_list(I_List <i_string> *list) while ((tmp= list->get())) delete tmp; } + + +base_list::base_list(const base_list &rhs, MEM_ROOT *mem_root) +{ + if (rhs.elements) + { + /* + It's okay to allocate an array of nodes at once: we never + call a destructor for list_node objects anyway. + */ + first= (list_node*) alloc_root(mem_root, + sizeof(list_node) * rhs.elements); + if (first) + { + elements= rhs.elements; + list_node *dst= first; + list_node *src= rhs.first; + for (; dst < first + elements - 1; dst++, src= src->next) + { + dst->info= src->info; + dst->next= dst + 1; + } + /* Copy the last node */ + dst->info= src->info; + dst->next= &end_of_list; + /* Setup 'last' member */ + last= &dst->next; + return; + } + } + elements= 0; + first= &end_of_list; + last= &first; +} diff --git a/sql/sql_list.h b/sql/sql_list.h index ba61a931e04..2e068f7f961 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -1,3 +1,5 @@ +#ifndef INCLUDES_MYSQL_SQL_LIST_H +#define INCLUDES_MYSQL_SQL_LIST_H /* Copyright (C) 2000-2003 MySQL AB This program is free software; you can redistribute it and/or modify @@ -25,16 +27,16 @@ class Sql_alloc public: static void *operator new(size_t size) throw () { - return (void*) sql_alloc((uint) size); + return sql_alloc(size); } static void *operator new[](size_t size) { - return (void*) sql_alloc((uint) size); + return sql_alloc(size); } static void *operator new[](size_t size, MEM_ROOT *mem_root) throw () - { return (void*) alloc_root(mem_root, (uint) size); } + { return alloc_root(mem_root, size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () - { return (void*) alloc_root(mem_root, (uint) size); } + { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* never called */ } @@ -63,21 +65,24 @@ public: pointer. */ -class list_node :public Sql_alloc + +/** + list_node - a node of a single-linked list. + @note We never call a destructor for instances of this class. +*/ + +struct list_node :public Sql_alloc { -public: list_node *next; void *info; list_node(void *info_par,list_node *next_par) :next(next_par),info(info_par) - {} + {} list_node() /* For end_of_list */ - { - info=0; - next= this; - } - friend class base_list; - friend class base_list_iterator; + { + info= 0; + next= this; + } }; @@ -93,12 +98,28 @@ public: inline void empty() { elements=0; first= &end_of_list; last=&first;} inline base_list() { empty(); } + /** + This is a shallow copy constructor that implicitly passes the ownership + from the source list to the new instance. The old instance is not + updated, so both objects end up sharing the same nodes. If one of + the instances then adds or removes a node, the other becomes out of + sync ('last' pointer), while still operational. Some old code uses and + relies on this behaviour. This logic is quite tricky: please do not use + it in any new code. + */ inline base_list(const base_list &tmp) :Sql_alloc() { elements= tmp.elements; first= tmp.first; last= elements ? tmp.last : &first; } + /** + Construct a deep copy of the argument in memory root mem_root. + The elements themselves are copied by pointer. If you also + need to copy elements by value, you should employ + list_copy_and_replace_each_value after creating a copy. + */ + base_list(const base_list &rhs, MEM_ROOT *mem_root); inline base_list(bool error) { } inline bool push_back(void *info) { @@ -185,6 +206,15 @@ public: elements+= list->elements; } } + /** + Swap two lists. + */ + inline void swap(base_list &rhs) + { + swap_variables(list_node *, first, rhs.first); + swap_variables(list_node **, last, rhs.last); + swap_variables(uint, elements, rhs.elements); + } inline list_node* last_node() { return *last; } inline list_node* first_node() { return first;} inline void *head() { return first->info; } @@ -349,6 +379,8 @@ template <class T> class List :public base_list public: inline List() :base_list() {} inline List(const List<T> &tmp) :base_list(tmp) {} + inline List(const List<T> &tmp, MEM_ROOT *mem_root) : + base_list(tmp, mem_root) {} inline bool push_back(T *a) { return base_list::push_back(a); } inline bool push_back(T *a, MEM_ROOT *mem_root) { return base_list::push_back(a, mem_root); } @@ -424,7 +456,7 @@ struct ilink } static void operator delete(void* ptr_arg, size_t size) { - my_free((gptr)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); + my_free((uchar*)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); } inline ilink() @@ -547,3 +579,32 @@ public: I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {} inline T* operator++(int) { return (T*) base_ilist_iterator::next(); } }; + +/** + Make a deep copy of each list element. + + @note A template function and not a template method of class List + is employed because of explicit template instantiation: + in server code there are explicit instantiations of List<T> and + an explicit instantiation of a template requires that any method + of the instantiated class used in the template can be resolved. + Evidently not all template arguments have clone() method with + the right signature. + + @return You must query the error state in THD for out-of-memory + situation after calling this function. +*/ + +template <typename T> +inline +void +list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root) +{ + /* Make a deep copy of each element */ + List_iterator<T> it(list); + T *el; + while ((el= it++)) + it.replace(el->clone(mem_root)); +} + +#endif // INCLUDES_MYSQL_SQL_LIST_H diff --git a/sql/sql_load.cc b/sql/sql_load.cc index a98797d7596..0138030487b 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -25,7 +25,7 @@ class READ_INFO { File file; - byte *buffer, /* Buffer for read text */ + uchar *buffer, /* Buffer for read text */ *end_of_buff; /* Data in bufferts ends here */ uint buff_length, /* Length of buffert */ max_length; /* Max length of row */ @@ -40,7 +40,7 @@ class READ_INFO { public: bool error,line_cuted,found_null,enclosed; - byte *row_start, /* Found row starts here */ + uchar *row_start, /* Found row starts here */ *row_end; /* Found row ends here */ CHARSET_INFO *read_charset; @@ -413,9 +413,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (error) { - if (transactional_table) - ha_autocommit_or_rollback(thd,error); - if (read_file_from_client) while (!read_info.next_line()) ; @@ -463,6 +460,9 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } } #endif /*!EMBEDDED_LIBRARY*/ + if (transactional_table) + ha_autocommit_or_rollback(thd,error); + error= -1; // Error on read goto err; } @@ -576,7 +576,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, continue; } it.rewind(); - byte *pos=read_info.row_start; + uchar *pos=read_info.row_start; #ifdef HAVE_purify read_info.row_end[0]=0; #endif @@ -611,7 +611,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, else { uint length; - byte save_chr; + uchar save_chr; if ((length=(uint) (read_info.row_end-pos)) > field->field_length) length=field->field_length; @@ -705,7 +705,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, while ((item= it++)) { uint length; - byte *pos; + uchar *pos; if (read_info.read_field()) break; @@ -914,7 +914,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, set_if_bigger(length,line_start.length()); stack=stack_pos=(int*) sql_alloc(sizeof(int)*length); - if (!(buffer=(byte*) my_malloc(buff_length+1,MYF(0)))) + if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0)))) error=1; /* purecov: inspected */ else { @@ -924,7 +924,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, (is_fifo ? READ_FIFO : READ_CACHE),0L,1, MYF(MY_WME))) { - my_free((gptr) buffer,MYF(0)); /* purecov: inspected */ + my_free((uchar*) buffer,MYF(0)); /* purecov: inspected */ error=1; } else @@ -955,7 +955,7 @@ READ_INFO::~READ_INFO() { if (need_end_io_cache) ::end_io_cache(&cache); - my_free((gptr) buffer,MYF(0)); + my_free((uchar*) buffer,MYF(0)); error=1; } } @@ -988,7 +988,7 @@ inline int READ_INFO::terminator(char *ptr,uint length) int READ_INFO::read_field() { int chr,found_enclosed_char; - byte *to,*new_buffer; + uchar *to,*new_buffer; found_null=0; if (found_end_of_line) @@ -1011,7 +1011,7 @@ int READ_INFO::read_field() if (chr == enclosed_char) { found_enclosed_char=enclosed_char; - *to++=(byte) chr; // If error + *to++=(uchar) chr; // If error } else { @@ -1053,7 +1053,7 @@ int READ_INFO::read_field() { if ((chr=GET) == my_b_EOF) { - *to++= (byte) escape_char; + *to++= (uchar) escape_char; goto found_eof; } /* @@ -1065,7 +1065,7 @@ int READ_INFO::read_field() */ if (escape_char != enclosed_char || chr == escape_char) { - *to++ = (byte) unescape((char) chr); + *to++ = (uchar) unescape((char) chr); continue; } PUSH(chr); @@ -1090,7 +1090,7 @@ int READ_INFO::read_field() { if ((chr=GET) == found_enclosed_char) { // Remove dupplicated - *to++ = (byte) chr; + *to++ = (uchar) chr; continue; } // End of enclosed field if followed by field_term or line_term @@ -1130,12 +1130,12 @@ int READ_INFO::read_field() return 0; } } - *to++ = (byte) chr; + *to++ = (uchar) chr; } /* ** We come here if buffer is too small. Enlarge it and continue */ - if (!(new_buffer=(byte*) my_realloc((char*) buffer,buff_length+1+IO_SIZE, + if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE, MYF(MY_WME)))) return (error=1); to=new_buffer + (to-buffer); @@ -1170,7 +1170,7 @@ found_eof: int READ_INFO::read_fixed_length() { int chr; - byte *to; + uchar *to; if (found_end_of_line) return 1; // One have to call next_line @@ -1190,10 +1190,10 @@ int READ_INFO::read_fixed_length() { if ((chr=GET) == my_b_EOF) { - *to++= (byte) escape_char; + *to++= (uchar) escape_char; goto found_eof; } - *to++ =(byte) unescape((char) chr); + *to++ =(uchar) unescape((char) chr); continue; } if (chr == line_term_char) @@ -1205,7 +1205,7 @@ int READ_INFO::read_fixed_length() return 0; } } - *to++ = (byte) chr; + *to++ = (uchar) chr; } row_end=to; // Found full line return 0; @@ -1236,7 +1236,7 @@ int READ_INFO::next_line() #ifdef USE_MB if (my_mbcharlen(read_charset, chr) > 1) { - for (int i=1; + for (uint i=1; chr != my_b_EOF && i<my_mbcharlen(read_charset, chr); i++) chr = GET; diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index b0ca7667a62..171ab55145a 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -118,7 +118,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) { struct handler_cb *next= cb->next; cb->action(); - my_free((gptr)cb, MYF(0)); + my_free((uchar*)cb, MYF(0)); cb= next; } diff --git a/sql/sql_map.cc b/sql/sql_map.cc index 36a47f1aefc..7b707f813fc 100644 --- a/sql/sql_map.cc +++ b/sql/sql_map.cc @@ -24,7 +24,7 @@ #include <sys/mman.h> #endif -mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_length) +mapped_files::mapped_files(const char * filename,uchar *magic,uint magic_length) { #ifdef HAVE_MMAP name=my_strdup(filename,MYF(0)); @@ -37,18 +37,18 @@ mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_lengt struct stat stat_buf; if (!fstat(file,&stat_buf)) { - if (!(map=(byte*) my_mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ, + if (!(map=(uchar*) my_mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ, MAP_SHARED | MAP_NORESERVE,file, 0L))) { error=errno; - my_error(ER_NO_FILE_MAPPING, MYF(0), (my_string) name, error); + my_error(ER_NO_FILE_MAPPING, MYF(0), (char *) name, error); } } if (map && memcmp(map,magic,magic_length)) { my_error(ER_WRONG_MAGIC, MYF(0), name); - VOID(my_munmap(map,size)); + VOID(my_munmap((char*) map,size)); map=0; } if (!map) @@ -66,7 +66,7 @@ mapped_files::~mapped_files() #ifdef HAVE_MMAP if (file >= 0) { - VOID(my_munmap(map,size)); + VOID(my_munmap((char*) map,size)); VOID(my_close(file,MYF(0))); file= -1; map=0; } @@ -82,7 +82,7 @@ static I_List<mapped_files> maps_in_use; ** else alloc new object */ -mapped_files *map_file(const my_string name,byte *magic,uint magic_length) +mapped_files *map_file(const char * name,uchar *magic,uint magic_length) { #ifdef HAVE_MMAP VOID(pthread_mutex_lock(&LOCK_mapped_file)); diff --git a/sql/sql_map.h b/sql/sql_map.h index d8eb64995aa..a1efba0da6f 100644 --- a/sql/sql_map.h +++ b/sql/sql_map.h @@ -21,11 +21,11 @@ #endif class mapped_files; -mapped_files *map_file(const my_string name,byte *magic,uint magic_length); +mapped_files *map_file(const char * name,uchar *magic,uint magic_length); void unmap_file(mapped_files *map); class mapped_files :public ilink { - byte *map; + uchar *map; ha_rows size; char *name; // name of mapped file File file; // >= 0 if open @@ -33,11 +33,11 @@ class mapped_files :public ilink { uint use_count; public: - mapped_files(const my_string name,byte *magic,uint magic_length); + mapped_files(const char * name,uchar *magic,uint magic_length); ~mapped_files(); friend class mapped_file; - friend mapped_files *map_file(const my_string name,byte *magic, + friend mapped_files *map_file(const char * name,uchar *magic, uint magic_length); friend void unmap_file(mapped_files *map); }; @@ -47,7 +47,7 @@ class mapped_file { mapped_files *file; public: - mapped_file(const my_string name,byte *magic,uint magic_length) + mapped_file(const char * name,uchar *magic,uint magic_length) { file=map_file(name,magic,magic_length); /* old or new map */ } @@ -55,7 +55,7 @@ public: { unmap_file(file); /* free map */ } - byte *map() + uchar *map() { return file->map; } diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index 818825d566b..dccfcbaf8ac 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -54,8 +54,8 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new new_select->linkage=OLAP_TYPE; new_select->olap=NON_EXISTING_ONE; new_select->group_list.elements=0; - new_select->group_list.first=(byte *)0; - new_select->group_list.next=(byte **)&new_select->group_list.first; + new_select->group_list.first=(uchar *)0; + new_select->group_list.next=(uchar **)&new_select->group_list.first; List<Item> privlist; List_iterator<Item> list_it(select_lex->item_list); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 06419010a24..2b43c6f0c40 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -39,6 +39,7 @@ "FUNCTION" : "PROCEDURE") static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); +static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); const char *any_db="*any*"; // Special symbol for check_access @@ -192,7 +193,7 @@ uint sql_command_flags[SQLCOM_END+1]; void init_update_queries(void) { - bzero((gptr) &sql_command_flags, sizeof(sql_command_flags)); + bzero((uchar*) &sql_command_flags, sizeof(sql_command_flags)); sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA; @@ -258,7 +259,6 @@ bool is_update_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_CHANGES_DATA) != 0; } - void execute_init_command(THD *thd, sys_var_str *init_command_var, rw_lock_t *var_mutex) { @@ -371,8 +371,9 @@ pthread_handler_t handle_bootstrap(void *arg) continue; thd->query_length=length; - thd->query= thd->memdup_w_gap(buff, length+1, - thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); + thd->query= (char*) thd->memdup_w_gap(buff, length+1, + thd->db_length+1+ + QUERY_CACHE_FLAGS_SIZE); thd->query[length] = '\0'; DBUG_PRINT("query",("%-.4096s",thd->query)); /* @@ -621,7 +622,7 @@ bool do_command(THD *thd) the client, the connection is closed or "net_wait_timeout" number of seconds has passed */ - net_set_read_timeout(net, thd->variables.net_wait_timeout); + my_net_set_read_timeout(net, thd->variables.net_wait_timeout); thd->clear_error(); // Clear error message @@ -653,7 +654,7 @@ bool do_command(THD *thd) } /* Restore read timeout value */ - net_set_read_timeout(net, thd->variables.net_read_timeout); + my_net_set_read_timeout(net, thd->variables.net_read_timeout); /* packet_length contains length of data, as it was stored in packet @@ -721,8 +722,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_INIT_DB: { LEX_STRING tmp; - statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]); thd->convert_string(&tmp, system_charset_info, packet, packet_length-1, thd->charset()); if (!mysql_change_db(thd, &tmp, FALSE)) @@ -757,15 +757,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } - statistic_increment(thd->status_var.com_other, &LOCK_status); + status_var_increment(thd->status_var.com_other); thd->enable_slow_log= opt_log_slow_admin_statements; - db.str= thd->alloc(db_len + tbl_len + 2); - db.length= db_len; + db.str= (char*) thd->alloc(db_len + tbl_len + 2); if (!db.str) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } + db.length= db_len; tbl_name= strmake(db.str, packet + 1, db_len)+1; strmake(tbl_name, packet + db_len + 2, tbl_len); mysql_table_dump(thd, &db, tbl_name); @@ -773,7 +773,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_CHANGE_USER: { - statistic_increment(thd->status_var.com_other, &LOCK_status); + status_var_increment(thd->status_var.com_other); char *user= (char*) packet, *packet_end= packet+ packet_length; char *passwd= strend(user)+1; @@ -784,12 +784,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Old clients send null-terminated string ('\0' for empty string) for password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). + + Cast *passwd to an unsigned char, so that it doesn't extend the sign + for *passwd > 127 and become 2**32-127 after casting to uint. */ char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; char *save_db; uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - *passwd++ : strlen(passwd)); + (uchar)(*passwd++) : strlen(passwd)); uint dummy_errors, save_db_length, db_length; int res; Security_context save_security_ctx= *thd->security_ctx; @@ -853,8 +856,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (save_user_connect) decrease_user_connections(save_user_connect); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ - x_free((gptr) save_db); - x_free((gptr) save_security_ctx.user); + x_free((uchar*) save_db); + x_free((uchar*) save_security_ctx.user); } break; } @@ -951,13 +954,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Locked closure of all tables */ TABLE_LIST table_list; LEX_STRING conv_name; - uint dummy; + size_t dummy; /* used as fields initializator */ lex_start(thd); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]); bzero((char*) &table_list,sizeof(table_list)); if (thd->copy_db_to(&table_list.db, &dummy)) break; @@ -979,7 +981,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } thd->query_length= (uint) (packet_end - packet); // Don't count end \0 - if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) + if (!(thd->query=fields= (char*) thd->memdup(packet,thd->query_length+1))) break; general_log_print(thd, command, "%s %s", table_list.table_name, fields); if (lower_case_table_names) @@ -988,8 +990,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, 0, 0, test(table_list.schema_table))) break; - if (grant_option && - check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) + if (check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) break; /* init structures for VIEW processing */ table_list.select_lex= &(thd->lex->select_lex); @@ -998,8 +999,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_reset_thd_for_next_command(thd); thd->lex-> - select_lex.table_list.link_in_list((byte*) &table_list, - (byte**) &table_list.next_local); + select_lex.table_list.link_in_list((uchar*) &table_list, + (uchar**) &table_list.next_local); thd->lex->add_to_query_tables(&table_list); /* switch on VIEW optimisation: do not fill temporary tables */ @@ -1023,8 +1024,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, LEX_STRING db, alias; HA_CREATE_INFO create_info; - statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]); if (thd->LEX_STRING_make(&db, packet, packet_length -1) || thd->LEX_STRING_make(&alias, db.str, db.length) || check_db_name(&db)) @@ -1043,8 +1043,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_DROP_DB: // QQ: To be removed { - statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]); LEX_STRING db; if (thd->LEX_STRING_make(&db, packet, packet_length - 1) || @@ -1073,7 +1072,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ushort flags; uint32 slave_server_id; - statistic_increment(thd->status_var.com_other,&LOCK_status); + status_var_increment(thd->status_var.com_other); thd->enable_slow_log= opt_log_slow_admin_statements; if (check_global_access(thd, REPL_SLAVE_ACL)) break; @@ -1099,8 +1098,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_REFRESH: { bool not_used; - statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]); ulong options= (ulong) (uchar) packet[0]; if (check_global_access(thd,RELOAD_ACL)) break; @@ -1112,7 +1110,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #ifndef EMBEDDED_LIBRARY case COM_SHUTDOWN: { - statistic_increment(thd->status_var.com_other, &LOCK_status); + status_var_increment(thd->status_var.com_other); if (check_global_access(thd,SHUTDOWN_ACL)) break; /* purecov: inspected */ /* @@ -1164,8 +1162,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif general_log_print(thd, command, NullS); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]); calc_sum_of_all_status(¤t_global_status_var); if (!(uptime= (ulong) (thd->start_time - server_start_time))) queries_per_second1000= 0; @@ -1195,18 +1192,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif #ifndef EMBEDDED_LIBRARY - VOID(my_net_write(net, buff, length)); + VOID(my_net_write(net, (uchar*) buff, length)); VOID(net_flush(net)); #endif break; } case COM_PING: - statistic_increment(thd->status_var.com_other, &LOCK_status); + status_var_increment(thd->status_var.com_other); send_ok(thd); // Tell client we are alive break; case COM_PROCESS_INFO: - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]); if (!thd->security_ctx->priv_user[0] && check_global_access(thd, PROCESS_ACL)) break; @@ -1217,15 +1213,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; case COM_PROCESS_KILL: { - statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_KILL]); ulong id=(ulong) uint4korr(packet); sql_kill(thd,id,false); break; } case COM_SET_OPTION: { - statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION]); uint opt_command= uint2korr(packet); switch (opt_command) { @@ -1244,7 +1239,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } case COM_DEBUG: - statistic_increment(thd->status_var.com_other, &LOCK_status); + status_var_increment(thd->status_var.com_other); if (check_global_access(thd, SUPER_ACL)) break; /* purecov: inspected */ mysql_print_status(); @@ -1394,7 +1389,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, #else { LEX_STRING db; - uint dummy; + size_t dummy; if (lex->select_lex.db == NULL && thd->copy_db_to(&lex->select_lex.db, &dummy)) { @@ -1495,7 +1490,7 @@ bool alloc_query(THD *thd, const char *packet, uint packet_length) } /* We must allocate some extra memory for query cache */ thd->query_length= 0; // Extra safety: Avoid races - if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), + if (!(thd->query= (char*) thd->memdup_w_gap((uchar*) (packet), packet_length, thd->db_length+ 1 + QUERY_CACHE_FLAGS_SIZE))) @@ -1574,7 +1569,7 @@ bool sp_process_definer(THD *thd) if (lex->definer == NULL) DBUG_RETURN(TRUE); - if (thd->slave_thread) + if (thd->slave_thread && lex->sphead) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; } else @@ -1783,8 +1778,7 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION } /* endif unlikely slave */ #endif - statistic_increment(thd->status_var.com_stat[lex->sql_command], - &LOCK_status); + status_var_increment(thd->status_var.com_stat[lex->sql_command]); switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -1826,6 +1820,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: + case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SELECT: thd->status_var.last_query_cost= 0.0; if (all_tables) @@ -1960,7 +1955,7 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_backup_table(thd, first_table); - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -1972,7 +1967,7 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_restore_table(thd, first_table); - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -2057,12 +2052,10 @@ mysql_execute_command(THD *thd) &first_table->grant.privilege, 0, 0, test(first_table->schema_table))) goto error; /* purecov: inspected */ - if (grant_option) - { - /* Check that the first table has CREATE privilege */ - if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) - goto error; - } + /* Check that the first table has CREATE privilege */ + if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) + goto error; + pthread_mutex_lock(&LOCK_active_mi); /* fetch_master_table will send the error to the client on failure. @@ -2094,23 +2087,47 @@ mysql_execute_command(THD *thd) // Skip first table, which is the table we are creating TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); TABLE_LIST *select_tables= lex->query_tables; + /* + Code below (especially in mysql_create_table() and select_create + methods) may modify HA_CREATE_INFO structure in LEX, so we have to + use a copy of this structure to make execution prepared statement- + safe. A shallow copy is enough as this code won't modify any memory + referenced from this structure. + */ + HA_CREATE_INFO create_info(lex->create_info); + /* + We need to copy alter_info for the same reasons of re-execution + safety, only in case of Alter_info we have to do (almost) a deep + copy. + */ + Alter_info alter_info(lex->alter_info, thd->mem_root); + + if (thd->is_fatal_error) + { + /* If out of memory when creating a copy of alter_info. */ + res= 1; + goto end_with_restore_list; + } if ((res= create_table_precheck(thd, select_tables, create_table))) goto end_with_restore_list; + /* Might have been updated in create_table_precheck */ + create_info.alias= create_table->alias; + #ifndef HAVE_READLINK - if (lex->create_info.data_file_name) + if (create_info.data_file_name) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "DATA DIRECTORY option ignored"); - if (lex->create_info.index_file_name) + if (create_info.index_file_name) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "INDEX DIRECTORY option ignored"); - lex->create_info.data_file_name=lex->create_info.index_file_name=0; + create_info.data_file_name= create_info.index_file_name= NULL; #else /* Fix names if symlinked tables */ - if (append_file_to_dir(thd, &lex->create_info.data_file_name, + if (append_file_to_dir(thd, &create_info.data_file_name, create_table->table_name) || - append_file_to_dir(thd, &lex->create_info.index_file_name, + append_file_to_dir(thd, &create_info.index_file_name, create_table->table_name)) goto end_with_restore_list; #endif @@ -2118,14 +2135,14 @@ mysql_execute_command(THD *thd) If we are using SET CHARSET without DEFAULT, add an implicit DEFAULT to not confuse old users. (This may change). */ - if ((lex->create_info.used_fields & + if ((create_info.used_fields & (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) == HA_CREATE_USED_CHARSET) { - lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET; - lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; - lex->create_info.default_table_charset= lex->create_info.table_charset; - lex->create_info.table_charset= 0; + create_info.used_fields&= ~HA_CREATE_USED_CHARSET; + create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; + create_info.default_table_charset= create_info.table_charset; + create_info.table_charset= 0; } /* The create-select command will open and read-lock the select table @@ -2164,7 +2181,7 @@ mysql_execute_command(THD *thd) select_lex->options|= SELECT_NO_UNLOCK; unit->set_limit(select_lex); - if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) + if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE)) { lex->link_first_table_back(create_table, link_to_local); create_table->create= TRUE; @@ -2176,7 +2193,7 @@ mysql_execute_command(THD *thd) Is table which we are changing used somewhere in other parts of query */ - if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) + if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE)) { TABLE_LIST *duplicate; create_table= lex->unlink_first_table(&link_to_local); @@ -2188,10 +2205,10 @@ mysql_execute_command(THD *thd) } } /* If we create merge table, we have to test tables in merge, too */ - if (lex->create_info.used_fields & HA_CREATE_USED_UNION) + if (create_info.used_fields & HA_CREATE_USED_UNION) { TABLE_LIST *tab; - for (tab= (TABLE_LIST*) lex->create_info.merge_list.first; + for (tab= (TABLE_LIST*) create_info.merge_list.first; tab; tab= tab->next_local) { @@ -2206,18 +2223,16 @@ mysql_execute_command(THD *thd) } /* - FIXME Temporary hack which will go away once Kostja pushes - his uber-fix for ALTER/CREATE TABLE. + select_create is currently not re-execution friendly and + needs to be created for every execution of a PS/SP. */ - lex->create_info.table_existed= 0; - if ((result= new select_create(create_table, - &lex->create_info, - lex->create_list, - lex->key_list, - select_lex->item_list, - lex->duplicates, - lex->ignore))) + &create_info, + &alter_info, + select_lex->item_list, + lex->duplicates, + lex->ignore, + select_tables))) { /* CREATE from SELECT give its SELECT_LEX for SELECT, @@ -2226,29 +2241,25 @@ mysql_execute_command(THD *thd) res= handle_select(thd, lex, result, 0); delete result; } - /* reset for PS */ - lex->create_list.empty(); - lex->key_list.empty(); } - else if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) + else if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE)) create_table= lex->unlink_first_table(&link_to_local); } else { /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ - if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) + if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->options|= OPTION_KEEP_LOG; /* regular create */ - if (lex->like_name) - res= mysql_create_like_table(thd, create_table, &lex->create_info, - lex->like_name); + if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) + res= mysql_create_like_table(thd, create_table, select_tables, + &create_info); else { res= mysql_create_table(thd, create_table->db, - create_table->table_name, &lex->create_info, - lex->create_list, - lex->key_list, 0, 0, 1); + create_table->table_name, &create_info, + &alter_info, 0, 0); } if (!res) send_ok(thd); @@ -2260,15 +2271,46 @@ end_with_restore_list: break; } case SQLCOM_CREATE_INDEX: + /* Fall through */ + case SQLCOM_DROP_INDEX: + /* + CREATE INDEX and DROP INDEX are implemented by calling ALTER + TABLE with proper arguments. + + In the future ALTER TABLE will notice that the request is to + only add indexes and create these one by one for the existing + table without having to do a full rebuild. + */ + { + /* Prepare stack copies to be re-execution safe */ + HA_CREATE_INFO create_info; + Alter_info alter_info(lex->alter_info, thd->mem_root); + + if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */ + goto error; + DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_one_table_access(thd, INDEX_ACL, all_tables)) goto error; /* purecov: inspected */ - thd->enable_slow_log= opt_log_slow_admin_statements; if (end_active_trans(thd)) goto error; - res= mysql_create_index(thd, first_table, lex->key_list); - break; + /* + Currently CREATE INDEX or DROP INDEX cause a full table rebuild + and thus classify as slow administrative statements just like + ALTER TABLE. + */ + thd->enable_slow_log= opt_log_slow_admin_statements; + + bzero((char*) &create_info, sizeof(create_info)); + create_info.db_type= 0; + create_info.row_type= ROW_TYPE_NOT_USED; + create_info.default_table_charset= thd->variables.collation_database; + res= mysql_alter_table(thd, first_table->db, first_table->table_name, + &create_info, first_table, &alter_info, + 0, (ORDER*) 0, 0); + break; + } #ifdef HAVE_REPLICATION case SQLCOM_SLAVE_START: { @@ -2311,10 +2353,21 @@ end_with_restore_list: ulong priv=0; ulong priv_needed= ALTER_ACL; /* + Code in mysql_alter_table() may modify its HA_CREATE_INFO argument, + so we have to use a copy of this structure to make execution + prepared statement- safe. A shallow copy is enough as no memory + referenced from this structure will be modified. + */ + HA_CREATE_INFO create_info(lex->create_info); + Alter_info alter_info(lex->alter_info, thd->mem_root); + + if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */ + goto error; + /* We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well as for RENAME TO, as being done by SQLCOM_RENAME_TABLE */ - if (lex->alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME)) + if (alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME)) priv_needed|= DROP_ACL; /* Must be set in the parser */ @@ -2326,32 +2379,30 @@ end_with_restore_list: is_schema_db(select_lex->db))|| check_merge_table_access(thd, first_table->db, (TABLE_LIST *) - lex->create_info.merge_list.first)) + create_info.merge_list.first)) goto error; /* purecov: inspected */ - if (grant_option) - { - if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) - goto error; - if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) - { // Rename of table - TABLE_LIST tmp_table; - bzero((char*) &tmp_table,sizeof(tmp_table)); - tmp_table.table_name= lex->name.str; - tmp_table.db=select_lex->db; - tmp_table.grant.privilege=priv; - if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, - UINT_MAX, 0)) - goto error; - } + if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) + goto error; + if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) + { // Rename of table + TABLE_LIST tmp_table; + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.table_name= lex->name.str; + tmp_table.db=select_lex->db; + tmp_table.grant.privilege=priv; + if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, + UINT_MAX, 0)) + goto error; } + /* Don't yet allow changing of symlinks with ALTER TABLE */ - if (lex->create_info.data_file_name) + if (create_info.data_file_name) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "DATA DIRECTORY option ignored"); - if (lex->create_info.index_file_name) + if (create_info.index_file_name) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "INDEX DIRECTORY option ignored"); - lex->create_info.data_file_name=lex->create_info.index_file_name=0; + create_info.data_file_name= create_info.index_file_name= NULL; /* ALTER TABLE ends previous transaction */ if (end_active_trans(thd)) goto error; @@ -2365,12 +2416,12 @@ end_with_restore_list: thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_alter_table(thd, select_lex->db, lex->name.str, - &lex->create_info, - first_table, lex->create_list, - lex->key_list, + &create_info, + first_table, + &alter_info, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->ignore, &lex->alter_info, 1); + lex->ignore); break; } case SQLCOM_RENAME_TABLE: @@ -2385,21 +2436,18 @@ end_with_restore_list: &table->next_local->grant.privilege, 0, 0, test(table->next_local->schema_table))) goto error; - if (grant_option) - { - TABLE_LIST old_list, new_list; - /* - we do not need initialize old_list and new_list because we will - come table[0] and table->next[0] there - */ - old_list= table[0]; - new_list= table->next_local[0]; - if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) || - (!test_all_bits(table->next_local->grant.privilege, - INSERT_ACL | CREATE_ACL) && - check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0))) - goto error; - } + TABLE_LIST old_list, new_list; + /* + we do not need initialize old_list and new_list because we will + come table[0] and table->next[0] there + */ + old_list= table[0]; + new_list= table->next_local[0]; + if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) || + (!test_all_bits(table->next_local->grant.privilege, + INSERT_ACL | CREATE_ACL) && + check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0))) + goto error; } query_cache_invalidate3(thd, first_table, 0); if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0)) @@ -2432,12 +2480,7 @@ end_with_restore_list: /* Ignore temporary tables if this is "SHOW CREATE VIEW" */ if (lex->only_view) first_table->skip_temporary= 1; - - if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db, - &first_table->grant.privilege, 0, 0, - test(first_table->schema_table))) - goto error; - if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0)) + if (check_show_create_table_access(thd, first_table)) goto error; res= mysqld_show_create(thd, first_table); break; @@ -2471,7 +2514,7 @@ end_with_restore_list: thd->query, thd->query_length, 0, FALSE); } } - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -2482,7 +2525,7 @@ end_with_restore_list: goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_check_table(thd, first_table, &lex->check_opt); - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -2506,7 +2549,7 @@ end_with_restore_list: thd->query, thd->query_length, 0, FALSE); } } - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -2518,7 +2561,7 @@ end_with_restore_list: goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? - mysql_recreate_table(thd, first_table, 1) : + mysql_recreate_table(thd, first_table) : mysql_optimize_table(thd, first_table, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) @@ -2533,7 +2576,7 @@ end_with_restore_list: thd->query, thd->query_length, 0, FALSE); } } - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; break; } @@ -2699,7 +2742,7 @@ end_with_restore_list: { /* Skip first table, which is the table we are inserting in */ TABLE_LIST *second_table= first_table->next_local; - select_lex->table_list.first= (byte*) second_table; + select_lex->table_list.first= (uchar*) second_table; select_lex->context.table_list= select_lex->context.first_name_resolution_table= second_table; res= mysql_insert_select_prepare(thd); @@ -2732,7 +2775,7 @@ end_with_restore_list: delete sel_result; } /* revert changes for SP */ - select_lex->table_list.first= (byte*) first_table; + select_lex->table_list.first= (uchar*) first_table; } /* @@ -2871,14 +2914,6 @@ end_with_restore_list: lex->drop_temporary); } break; - case SQLCOM_DROP_INDEX: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_one_table_access(thd, INDEX_ACL, all_tables)) - goto error; /* purecov: inspected */ - if (end_active_trans(thd)) - goto error; - res= mysql_drop_index(thd, first_table, &lex->alter_info); - break; case SQLCOM_SHOW_PROCESSLIST: if (!thd->security_ctx->priv_user[0] && check_global_access(thd,PROCESS_ACL)) @@ -2889,9 +2924,6 @@ end_with_restore_list: thd->security_ctx->priv_user), lex->verbose); break; - case SQLCOM_SHOW_STORAGE_ENGINES: - res= mysqld_show_storage_engines(thd); - break; case SQLCOM_SHOW_AUTHORS: res= mysqld_show_authors(thd); break; @@ -2911,7 +2943,7 @@ end_with_restore_list: goto error; #else { - if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0)) + if (check_access(thd, FILE_ACL, any_db,0,0,0,0)) goto error; res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS); break; @@ -3018,6 +3050,12 @@ end_with_restore_list: break; case SQLCOM_CREATE_DB: { + /* + As mysql_create_db() may modify HA_CREATE_INFO structure passed to + it, we need to use a copy of LEX::create_info to make execution + prepared statement- safe. + */ + HA_CREATE_INFO create_info(lex->create_info); if (end_active_trans(thd)) { res= -1; @@ -3050,7 +3088,7 @@ end_with_restore_list: is_schema_db(lex->name.str))) break; res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : - lex->name.str), &lex->create_info, 0); + lex->name.str), &create_info, 0); break; } case SQLCOM_DROP_DB: @@ -3143,6 +3181,7 @@ end_with_restore_list: case SQLCOM_ALTER_DB: { LEX_STRING *db= &lex->name; + HA_CREATE_INFO create_info(lex->create_info); if (check_db_name(db)) { my_error(ER_WRONG_DB_NAME, MYF(0), db->str); @@ -3172,7 +3211,7 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_alter_db(thd, db->str, &lex->create_info); + res= mysql_alter_db(thd, db->str, &create_info); break; } case SQLCOM_SHOW_CREATE_DB: @@ -3358,8 +3397,7 @@ end_with_restore_list: uint grants= lex->all_privileges ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL) : lex->grant; - if (grant_option && - check_grant_routine(thd, grants | GRANT_ACL, all_tables, + if (check_grant_routine(thd, grants | GRANT_ACL, all_tables, lex->type == TYPE_ENUM_PROCEDURE, 0)) goto error; /* Conditionally writes to binlog */ @@ -3370,10 +3408,8 @@ end_with_restore_list: } else { - if (grant_option && check_grant(thd, - (lex->grant | lex->grant_tot_col | - GRANT_ACL), - all_tables, 0, UINT_MAX, 0)) + if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL), + all_tables, 0, UINT_MAX, 0)) goto error; /* Conditionally writes to binlog */ res= mysql_table_grant(thd, all_tables, lex->users_list, @@ -3763,7 +3799,7 @@ create_sp_error: goto error; } - my_bool nsok= thd->net.no_send_ok; + my_bool save_no_send_ok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; if (sp->m_flags & sp_head::MULTI_RESULTS) { @@ -3774,7 +3810,7 @@ create_sp_error: back */ my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str); - thd->net.no_send_ok= nsok; + thd->net.no_send_ok= save_no_send_ok; goto error; } /* @@ -3790,7 +3826,7 @@ create_sp_error: if (check_routine_access(thd, EXECUTE_ACL, sp->m_db.str, sp->m_name.str, TRUE, FALSE)) { - thd->net.no_send_ok= nsok; + thd->net.no_send_ok= save_no_send_ok; goto error; } #endif @@ -3815,7 +3851,7 @@ create_sp_error: thd->variables.select_limit= select_limit; - thd->net.no_send_ok= nsok; + thd->net.no_send_ok= save_no_send_ok; thd->server_status&= ~bits_to_be_cleared; if (!res) @@ -3883,11 +3919,15 @@ create_sp_error: already puts on CREATE FUNCTION. */ /* Conditionally writes to binlog */ - if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - sp_result= sp_update_procedure(thd, lex->spname, - &lex->sp_chistics); - else - sp_result= sp_update_function(thd, lex->spname, &lex->sp_chistics); + + int type= lex->sql_command == SQLCOM_ALTER_PROCEDURE ? + TYPE_ENUM_PROCEDURE : + TYPE_ENUM_FUNCTION; + + sp_result= sp_update_routine(thd, + type, + lex->spname, + &lex->sp_chistics); } } switch (sp_result) @@ -3937,10 +3977,12 @@ create_sp_error: } #endif /* Conditionally writes to binlog */ - if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - sp_result= sp_drop_procedure(thd, lex->spname); - else - sp_result= sp_drop_function(thd, lex->spname); + + int type= lex->sql_command == SQLCOM_DROP_PROCEDURE ? + TYPE_ENUM_PROCEDURE : + TYPE_ENUM_FUNCTION; + + sp_result= sp_drop_routine(thd, type, lex->spname); } else { @@ -3997,8 +4039,8 @@ create_sp_error: } case SQLCOM_SHOW_CREATE_PROC: { - if (sp_show_create_procedure(thd, lex->spname) != SP_OK) - { /* We don't distinguish between errors for now */ + if (sp_show_create_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname)) + { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), SP_COM_STRING(lex), lex->spname->m_name.str); goto error; @@ -4007,8 +4049,8 @@ create_sp_error: } case SQLCOM_SHOW_CREATE_FUNC: { - if (sp_show_create_function(thd, lex->spname) != SP_OK) - { /* We don't distinguish between errors for now */ + if (sp_show_create_routine(thd, TYPE_ENUM_FUNCTION, lex->spname)) + { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), SP_COM_STRING(lex), lex->spname->m_name.str); goto error; @@ -4018,14 +4060,14 @@ create_sp_error: #ifdef NOT_USED case SQLCOM_SHOW_STATUS_PROC: { - res= sp_show_status_procedure(thd, (lex->wild ? - lex->wild->ptr() : NullS)); + res= sp_show_status_routine(thd, TYPE_ENUM_PROCEDURE, + (lex->wild ? lex->wild->ptr() : NullS)); break; } case SQLCOM_SHOW_STATUS_FUNC: { - res= sp_show_status_function(thd, (lex->wild ? - lex->wild->ptr() : NullS)); + res= sp_show_status_routine(thd, TYPE_ENUM_FUNCTION, + (lex->wild ? lex->wild->ptr() : NullS)); break; } #endif @@ -4488,8 +4530,7 @@ bool check_single_table_access(THD *thd, ulong privilege, goto deny; /* Show only 1 table for check_grant */ - if (grant_option && - !(all_tables->belong_to_view && + if (!(all_tables->belong_to_view && (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) && check_grant(thd, privilege, all_tables, 0, 1, no_errors)) goto deny; @@ -4570,7 +4611,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, Security_context *sctx= thd->security_ctx; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; - bool db_is_pattern= test(want_access & GRANT_ACL); + /* + GRANT command: + In case of database level grant the database name may be a pattern, + in case of table|column level grant the database name can not be a pattern. + We use 'dont_check_global_grants' as a flag to determine + if it's database level grant command + (see SQLCOM_GRANT case, mysql_execute_command() function) and + set db_is_pattern according to 'dont_check_global_grants' value. + */ + bool db_is_pattern= (test(want_access & GRANT_ACL) && + dont_check_global_grants); #endif ulong dummy; DBUG_ENTER("check_access"); @@ -4657,9 +4708,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, db_access, want_access)); db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access); - /* grant_option is set if there exists a single table or column grant */ if (db_access == want_access || - (grant_option && !dont_check_global_grants && + (!dont_check_global_grants && !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS)))) DBUG_RETURN(FALSE); /* Ok */ @@ -4758,8 +4808,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) test(dst_table->schema_table))) return FALSE; - return (grant_option && - check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE)); + return (check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE)); } default: break; @@ -4796,8 +4845,6 @@ bool check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, bool no_errors) { - uint found=0; - ulong found_access=0; #ifndef NO_EMBEDDED_ACCESS_CHECKS TABLE_LIST *org_tables= tables; #endif @@ -4848,26 +4895,17 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, tables->grant.privilege= want_access; else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0) { - if (found && !grant_option) // db already checked - tables->grant.privilege=found_access; - else - { - if (check_access(thd,want_access,tables->db,&tables->grant.privilege, + if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 0, no_errors, test(tables->schema_table))) - goto deny; // Access denied - found_access=tables->grant.privilege; - found=1; - } + goto deny; // Access denied } else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 0, no_errors, test(tables->schema_table))) goto deny; } thd->security_ctx= backup_ctx; - if (grant_option) - return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, + return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, test(want_access & EXTRA_ACL), UINT_MAX, no_errors); - return FALSE; deny: thd->security_ctx= backup_ctx; return TRUE; @@ -4897,11 +4935,10 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, return TRUE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (grant_option) return check_grant_routine(thd, want_access, tables, is_proc, no_errors); -#endif - +#else return FALSE; +#endif } @@ -4963,7 +5000,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) if (!check_access(thd, access, table->db, &table->grant.privilege, 0, 1, test(table->schema_table)) && - !grant_option || !check_grant(thd, access, table, 0, 1, 1)) + !check_grant(thd, access, table, 0, 1, 1)) DBUG_RETURN(0); } } @@ -4996,17 +5033,14 @@ bool check_merge_table_access(THD *thd, char *db, Check stack size; Send error if there isn't enough stack to continue ****************************************************************************/ -#if STACK_DIRECTION < 0 -#define used_stack(A,B) (long) (A - B) -#else -#define used_stack(A,B) (long) (B - A) -#endif +#ifndef EMBEDDED_LIBRARY + +#define used_stack(A,B) (long)(A > B ? A - B : B - A) #ifndef DBUG_OFF long max_stack_used; #endif -#ifndef EMBEDDED_LIBRARY /* Note: The 'buf' parameter is necessary, even if it is unused here. - fix_fields functions has a "dummy" buffer large enough for the @@ -5014,7 +5048,7 @@ long max_stack_used; - Passing to check_stack_overrun() prevents the compiler from removing it. */ bool check_stack_overrun(THD *thd, long margin, - char *buf __attribute__((unused))) + uchar *buf __attribute__((unused))) { long stack_used; DBUG_ASSERT(thd == current_thd); @@ -5046,19 +5080,19 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) if (!lex->yacc_yyvs) old_info= *yystacksize; *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX); - if (!(lex->yacc_yyvs= (char*) - my_realloc((gptr) lex->yacc_yyvs, + if (!(lex->yacc_yyvs= (uchar*) + my_realloc(lex->yacc_yyvs, *yystacksize*sizeof(**yyvs), MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || - !(lex->yacc_yyss= (char*) - my_realloc((gptr) lex->yacc_yyss, + !(lex->yacc_yyss= (uchar*) + my_realloc(lex->yacc_yyss, *yystacksize*sizeof(**yyss), MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) return 1; if (old_info) { // Copy old info from stack - memcpy(lex->yacc_yyss, (gptr) *yyss, old_info*sizeof(**yyss)); - memcpy(lex->yacc_yyvs, (gptr) *yyvs, old_info*sizeof(**yyvs)); + memcpy(lex->yacc_yyss, (uchar*) *yyss, old_info*sizeof(**yyss)); + memcpy(lex->yacc_yyvs, (uchar*) *yyvs, old_info*sizeof(**yyvs)); } *yyss=(short*) lex->yacc_yyss; *yyvs=(YYSTYPE*) lex->yacc_yyvs; @@ -5320,12 +5354,11 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, sp_cache_flush_obsolete(&thd->sp_func_cache); Lex_input_stream lip(thd, inBuf, length); - thd->m_lip= &lip; - int err= MYSQLparse(thd); + bool err= parse_sql(thd, &lip); *found_semicolon= lip.found_semicolon; - if (!err && ! thd->is_fatal_error) + if (!err) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && @@ -5348,8 +5381,8 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, PROCESSLIST. Note that we don't need LOCK_thread_count to modify query_length. */ - if (lip.found_semicolon && - (thd->query_length= (ulong)(lip.found_semicolon - thd->query))) + if (*found_semicolon && + (thd->query_length= (ulong)(*found_semicolon - thd->query))) thd->query_length--; /* Actually execute the query */ mysql_execute_command(thd); @@ -5403,12 +5436,10 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) DBUG_ENTER("mysql_test_parse_for_slave"); Lex_input_stream lip(thd, inBuf, length); - thd->m_lip= &lip; lex_start(thd); mysql_reset_thd_for_next_command(thd); - int err= MYSQLparse((void*) thd); - if (!err && ! thd->is_fatal_error && + if (!parse_sql(thd, &lip) && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) error= 1; /* Ignore question */ thd->end_statement(); @@ -5433,7 +5464,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, List<String> *interval_list, CHARSET_INFO *cs, uint uint_geom_type) { - register create_field *new_field; + register Create_field *new_field; LEX *lex= thd->lex; DBUG_ENTER("add_field_to_list"); @@ -5445,18 +5476,22 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, } if (type_modifier & PRI_KEY_FLAG) { - lex->col_list.push_back(new key_part_spec(field_name->str, 0)); - lex->key_list.push_back(new Key(Key::PRIMARY, NullS, - &default_key_create_info, - 0, lex->col_list)); + Key *key; + lex->col_list.push_back(new Key_part_spec(field_name->str, 0)); + key= new Key(Key::PRIMARY, NullS, + &default_key_create_info, + 0, lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); } if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG)) { - lex->col_list.push_back(new key_part_spec(field_name->str, 0)); - lex->key_list.push_back(new Key(Key::UNIQUE, NullS, - &default_key_create_info, 0, - lex->col_list)); + Key *key; + lex->col_list.push_back(new Key_part_spec(field_name->str, 0)); + key= new Key(Key::UNIQUE, NullS, + &default_key_create_info, 0, + lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); } @@ -5510,13 +5545,13 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'"); } - if (!(new_field= new create_field()) || + if (!(new_field= new Create_field()) || new_field->init(thd, field_name->str, type, length, decimals, type_modifier, default_value, on_update_value, comment, change, interval_list, cs, uint_geom_type)) DBUG_RETURN(1); - lex->create_list.push_back(new_field); + lex->alter_info.create_list.push_back(new_field); lex->last_field=new_field; DBUG_RETURN(0); } @@ -5541,7 +5576,7 @@ add_proc_to_list(THD* thd, Item *item) *item_ptr= item; order->item=item_ptr; order->free_me=0; - thd->lex->proc_list.link_in_list((byte*) order,(byte**) &order->next); + thd->lex->proc_list.link_in_list((uchar*) order,(uchar**) &order->next); return 0; } @@ -5563,7 +5598,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) order->free_me=0; order->used=0; order->counter_used= 0; - list.link_in_list((byte*) order,(byte**) &order->next); + list.link_in_list((uchar*) order,(uchar**) &order->next); DBUG_RETURN(0); } @@ -5628,7 +5663,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0)); DBUG_RETURN(0); } - if (!(alias_str=thd->memdup(alias_str,table->table.length+1))) + if (!(alias_str= (char*) thd->memdup(alias_str,table->table.length+1))) DBUG_RETURN(0); } if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) @@ -5715,7 +5750,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, previous table reference to 'ptr'. Here we also add one element to the list 'table_list'. */ - table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local); + table_list.link_in_list((uchar*) ptr, (uchar**) &ptr->next_local); ptr->next_name_resolution_table= NULL; /* Link table in global list (all used tables) */ lex->add_to_query_tables(ptr); @@ -5754,7 +5789,7 @@ bool st_select_lex::init_nested_join(THD *thd) sizeof(NESTED_JOIN)))) DBUG_RETURN(1); nested_join= ptr->nested_join= - ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); + ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); join_list->push_front(ptr); ptr->embedding= embedding; @@ -5840,7 +5875,7 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) sizeof(NESTED_JOIN)))) DBUG_RETURN(0); nested_join= ptr->nested_join= - ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); + ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); ptr->embedding= embedding; ptr->join_list= join_list; @@ -6433,7 +6468,7 @@ bool append_file_to_dir(THD *thd, const char **filename_ptr, /* Fix is using unix filename format on dos */ strmov(buff,*filename_ptr); end=convert_dirname(buff, *filename_ptr, NullS); - if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1))) + if (!(ptr= (char*) thd->alloc((size_t) (end-buff) + strlen(table_name)+1))) return 1; // End of memory *filename_ptr=ptr; strxmov(ptr,buff,table_name,NullS); @@ -6539,55 +6574,6 @@ Item * all_any_subquery_creator(Item *left_expr, /* - CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with - the proper arguments. This isn't very fast but it should work for most - cases. - - In the future ALTER TABLE will notice that only added indexes - and create these one by one for the existing table without having to do - a full rebuild. - - One should normally create all indexes with CREATE TABLE or ALTER TABLE. -*/ - -bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) -{ - List<create_field> fields; - ALTER_INFO alter_info; - alter_info.flags= ALTER_ADD_INDEX; - HA_CREATE_INFO create_info; - DBUG_ENTER("mysql_create_index"); - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= 0; - create_info.default_table_charset= thd->variables.collation_database; - create_info.row_type= ROW_TYPE_NOT_USED; - DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, - &create_info, table_list, - fields, keys, 0, (ORDER*)0, - 0, &alter_info, 1)); -} - - -bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) -{ - List<create_field> fields; - List<Key> keys; - HA_CREATE_INFO create_info; - DBUG_ENTER("mysql_drop_index"); - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= 0; - create_info.default_table_charset= thd->variables.collation_database; - create_info.row_type= ROW_TYPE_NOT_USED; - alter_info->clear(); - alter_info->flags= ALTER_DROP_INDEX; - DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, - &create_info, table_list, - fields, keys, 0, (ORDER*)0, - 0, alter_info, 1)); -} - - -/* Multi update query pre-check SYNOPSIS @@ -6624,12 +6610,11 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) else if ((check_access(thd, UPDATE_ACL, table->db, &table->grant.privilege, 0, 1, test(table->schema_table)) || - grant_option && check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) && (check_access(thd, SELECT_ACL, table->db, &table->grant.privilege, 0, 0, test(table->schema_table)) || - grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) + check_grant(thd, SELECT_ACL, table, 0, 1, 0))) DBUG_RETURN(TRUE); table->table_in_first_from_clause= 1; @@ -6647,7 +6632,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) if (check_access(thd, SELECT_ACL, table->db, &table->grant.privilege, 0, 0, test(table->schema_table)) || - grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)) + check_grant(thd, SELECT_ACL, table, 0, 1, 0)) DBUG_RETURN(TRUE); } } @@ -6854,6 +6839,25 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables) } +/** + @brief Check privileges for SHOW CREATE TABLE statement. + + @param thd Thread context + @param table Target table + + @retval TRUE Failure + @retval FALSE Success +*/ + +static bool check_show_create_table_access(THD *thd, TABLE_LIST *table) +{ + return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db, + &table->grant.privilege, 0, 0, + test(table->schema_table)) || + check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0); +} + + /* CREATE TABLE query pre-check @@ -6879,7 +6883,6 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? CREATE_TMP_ACL : CREATE_ACL); - lex->create_info.alias= create_table->alias; if (check_access(thd, want_priv, create_table->db, &create_table->grant.privilege, 0, 0, test(create_table->schema_table)) || @@ -6887,7 +6890,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, (TABLE_LIST *) lex->create_info.merge_list.first)) goto err; - if (grant_option && want_priv != CREATE_TMP_ACL && + if (want_priv != CREATE_TMP_ACL && check_grant(thd, want_priv, create_table, 0, 1, 0)) goto err; @@ -6919,6 +6922,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, if (tables && check_table_access(thd, SELECT_ACL, tables,0)) goto err; } + else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE) + { + if (check_show_create_table_access(thd, tables)) + goto err; + } error= FALSE; err: @@ -7123,3 +7131,34 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg, my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_char_length); return TRUE; } + + +extern int MYSQLparse(void *thd); // from sql_yacc.cc + + +/** + This is a wrapper of MYSQLparse(). All the code should call parse_sql() + instead of MYSQLparse(). + + @param thd Thread context. + @param lip Lexer context. + + @return Error status. + @retval FALSE on success. + @retval TRUE on parsing error. +*/ + +bool parse_sql(THD *thd, Lex_input_stream *lip) +{ + bool err_status; + + DBUG_ASSERT(thd->m_lip == NULL); + + thd->m_lip= lip; + + err_status= MYSQLparse(thd) != 0 || thd->is_fatal_error; + + thd->m_lip= NULL; + + return err_status; +} diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e49c2642924..407a0b3dcf2 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -123,47 +123,23 @@ uint32 get_partition_id_hash_sub(partition_info *part_info); uint32 get_partition_id_key_sub(partition_info *part_info); uint32 get_partition_id_linear_hash_sub(partition_info *part_info); uint32 get_partition_id_linear_key_sub(partition_info *part_info); -#endif - static uint32 get_next_partition_via_walking(PARTITION_ITERATOR*); +static void set_up_range_analysis_info(partition_info *part_info); static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR*); +#endif + uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter); uint32 get_next_partition_id_list(PARTITION_ITERATOR* part_iter); int get_part_iter_for_interval_via_mapping(partition_info *part_info, bool is_subpart, - char *min_value, char *max_value, + uchar *min_value, uchar *max_value, uint flags, PARTITION_ITERATOR *part_iter); int get_part_iter_for_interval_via_walking(partition_info *part_info, bool is_subpart, - char *min_value, char *max_value, + uchar *min_value, uchar *max_value, uint flags, PARTITION_ITERATOR *part_iter); -static void set_up_range_analysis_info(partition_info *part_info); - -/* - A routine used by the parser to decide whether we are specifying a full - partitioning or if only partitions to add or to split. - - SYNOPSIS - is_partition_management() - lex Reference to the lex object - - RETURN VALUE - TRUE Yes, it is part of a management partition command - FALSE No, not a management partition command - - DESCRIPTION - This needs to be outside of WITH_PARTITION_STORAGE_ENGINE since it is - used from the sql parser that doesn't have any #ifdef's -*/ - -my_bool is_partition_management(LEX *lex) -{ - return (lex->sql_command == SQLCOM_ALTER_TABLE && - (lex->alter_info.flags == ALTER_ADD_PARTITION || - lex->alter_info.flags == ALTER_REORGANIZE_PARTITION)); -} #ifdef WITH_PARTITION_STORAGE_ENGINE /* @@ -318,8 +294,8 @@ bool check_reorganise_list(partition_info *new_part_info, > 0 Error code */ -int get_parts_for_update(const byte *old_data, byte *new_data, - const byte *rec0, partition_info *part_info, +int get_parts_for_update(const uchar *old_data, uchar *new_data, + const uchar *rec0, partition_info *part_info, uint32 *old_part_id, uint32 *new_part_id, longlong *new_func_value) { @@ -392,7 +368,7 @@ int get_parts_for_update(const byte *old_data, byte *new_data, calculate the partition id. */ -int get_part_for_delete(const byte *buf, const byte *rec0, +int get_part_for_delete(const uchar *buf, const uchar *rec0, partition_info *part_info, uint32 *part_id) { int error; @@ -931,7 +907,7 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, context->table_list= &tables; context->first_name_resolution_table= &tables; context->last_name_resolution_table= NULL; - func_expr->walk(&Item::change_context_processor, 0, (byte*) context); + func_expr->walk(&Item::change_context_processor, 0, (uchar*) context); save_where= thd->where; thd->where= "partition function"; /* @@ -1697,7 +1673,7 @@ end: static int add_write(File fptr, const char *buf, uint len) { - uint len_written= my_write(fptr, (const byte*)buf, len, MYF(0)); + uint len_written= my_write(fptr, (const uchar*)buf, len, MYF(0)); if (likely(len == len_written)) return 0; @@ -2144,13 +2120,13 @@ char *generate_partition_syntax(partition_info *part_info, goto close_file; *buf_length= (uint)buffer_length; if (use_sql_alloc) - buf= sql_alloc(*buf_length+1); + buf= (char*) sql_alloc(*buf_length+1); else - buf= my_malloc(*buf_length+1, MYF(MY_WME)); + buf= (char*) my_malloc(*buf_length+1, MYF(MY_WME)); if (!buf) goto close_file; - if (unlikely(my_read(fptr, (byte*)buf, *buf_length, MYF(MY_FNABP)))) + if (unlikely(my_read(fptr, (uchar*)buf, *buf_length, MYF(MY_FNABP)))) { if (!use_sql_alloc) my_free(buf, MYF(0)); @@ -2413,8 +2389,8 @@ static uint32 get_part_id_linear_key(partition_info *part_info, */ static void copy_to_part_field_buffers(Field **ptr, - char **field_bufs, - char **restore_ptr) + uchar **field_bufs, + uchar **restore_ptr) { Field *field; while ((field= *(ptr++))) @@ -2425,7 +2401,7 @@ static void copy_to_part_field_buffers(Field **ptr, { CHARSET_INFO *cs= ((Field_str*)field)->charset(); uint len= field->pack_length(); - char *field_buf= *field_bufs; + uchar *field_buf= *field_bufs; /* We only use the field buffer for VARCHAR and CHAR strings which isn't of a binary collation. We also only use the @@ -2436,17 +2412,17 @@ static void copy_to_part_field_buffers(Field **ptr, if (field->type() == MYSQL_TYPE_VARCHAR) { uint len_bytes= ((Field_varstring*)field)->length_bytes; - my_strnxfrm(cs, (uchar*)(field_buf + len_bytes), (len - len_bytes), - (uchar*)(field->ptr + len_bytes), field->field_length); + my_strnxfrm(cs, field_buf + len_bytes, (len - len_bytes), + field->ptr + len_bytes, field->field_length); if (len_bytes == 1) - *field_buf= (uchar)field->field_length; + *field_buf= (uchar) field->field_length; else int2store(field_buf, field->field_length); } else { - my_strnxfrm(cs, (uchar*)field_buf, len, - (uchar*)field->ptr, field->field_length); + my_strnxfrm(cs, field_buf, len, + field->ptr, field->field_length); } field->ptr= field_buf; } @@ -2465,7 +2441,7 @@ static void copy_to_part_field_buffers(Field **ptr, RETURN VALUES */ -static void restore_part_field_pointers(Field **ptr, char **restore_ptr) +static void restore_part_field_pointers(Field **ptr, uchar **restore_ptr) { Field *field; while ((field= *(ptr++))) @@ -3307,16 +3283,16 @@ static bool check_part_func_bound(Field **ptr) get the partition identity and restore field pointers afterwards. */ -static uint32 get_sub_part_id_from_key(const TABLE *table,byte *buf, +static uint32 get_sub_part_id_from_key(const TABLE *table,uchar *buf, KEY *key_info, const key_range *key_spec) { - byte *rec0= table->record[0]; + uchar *rec0= table->record[0]; partition_info *part_info= table->part_info; uint32 part_id; DBUG_ENTER("get_sub_part_id_from_key"); - key_restore(buf, (byte*)key_spec->key, key_info, key_spec->length); + key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length); if (likely(rec0 == buf)) part_id= part_info->get_subpartition_id(part_info); else @@ -3350,16 +3326,16 @@ static uint32 get_sub_part_id_from_key(const TABLE *table,byte *buf, get the partition identity and restore field pointers afterwards. */ -bool get_part_id_from_key(const TABLE *table, byte *buf, KEY *key_info, +bool get_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, uint32 *part_id) { bool result; - byte *rec0= table->record[0]; + uchar *rec0= table->record[0]; partition_info *part_info= table->part_info; longlong func_value; DBUG_ENTER("get_part_id_from_key"); - key_restore(buf, (byte*)key_spec->key, key_info, key_spec->length); + key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length); if (likely(rec0 == buf)) result= part_info->get_part_partition_id(part_info, part_id, &func_value); @@ -3395,18 +3371,18 @@ bool get_part_id_from_key(const TABLE *table, byte *buf, KEY *key_info, get the partition identity and restore field pointers afterwards. */ -void get_full_part_id_from_key(const TABLE *table, byte *buf, +void get_full_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, part_id_range *part_spec) { bool result; partition_info *part_info= table->part_info; - byte *rec0= table->record[0]; + uchar *rec0= table->record[0]; longlong func_value; DBUG_ENTER("get_full_part_id_from_key"); - key_restore(buf, (byte*)key_spec->key, key_info, key_spec->length); + key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length); if (likely(rec0 == buf)) result= part_info->get_partition_id(part_info, &part_spec->start_part, &func_value); @@ -3494,7 +3470,7 @@ void prune_partition_set(const TABLE *table, part_id_range *part_spec) RETURN VALUE part_spec */ -void get_partition_set(const TABLE *table, byte *buf, const uint index, +void get_partition_set(const TABLE *table, uchar *buf, const uint index, const key_range *key_spec, part_id_range *part_spec) { partition_info *part_info= table->part_info; @@ -3720,7 +3696,6 @@ bool mysql_unpack_partition(THD *thd, thd->variables.character_set_client= system_charset_info; Lex_input_stream lip(thd, part_buf, part_info_len); - thd->m_lip= &lip; lex_start(thd); /* @@ -3749,7 +3724,7 @@ bool mysql_unpack_partition(THD *thd, lex.part_info->part_state= part_state; lex.part_info->part_state_len= part_state_len; DBUG_PRINT("info", ("Parse: %s", part_buf)); - if (MYSQLparse((void*)thd) || thd->is_fatal_error) + if (parse_sql(thd, &lip)) { thd->free_items(); goto end; @@ -3776,20 +3751,15 @@ bool mysql_unpack_partition(THD *thd, ha_legacy_type(default_db_type))); if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE) { - if (old_lex->like_name) + if (old_lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE) { /* - This code is executed when we do a CREATE TABLE t1 LIKE t2 - old_lex->like_name contains the t2 and the table we are opening has - name t1. + This code is executed when we create table in CREATE TABLE t1 LIKE t2. + old_lex->query_tables contains table list element for t2 and the table + we are opening has name t1. */ - Table_ident *table_ident= old_lex->like_name; - char *src_db= table_ident->db.str ? table_ident->db.str : thd->db; - char *src_table= table_ident->table.str; - char buf[FN_REFLEN]; - build_table_filename(buf, sizeof(buf), src_db, src_table, "", 0); - if (partition_default_handling(table, part_info, - FALSE, buf)) + if (partition_default_handling(table, part_info, FALSE, + old_lex->query_tables->table->s->path.str)) { result= TRUE; goto end; @@ -3835,9 +3805,9 @@ bool mysql_unpack_partition(THD *thd, char *part_func_string= NULL; char *subpart_func_string= NULL; if ((part_func_len && - !((part_func_string= thd->alloc(part_func_len)))) || + !((part_func_string= (char*) thd->alloc(part_func_len)))) || (subpart_func_len && - !((subpart_func_string= thd->alloc(subpart_func_len))))) + !((subpart_func_string= (char*) thd->alloc(subpart_func_len))))) { mem_alloc_error(part_func_len); thd->free_items(); @@ -4130,7 +4100,7 @@ error: change patterns. */ -uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, +uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, handlerton *old_db_type, bool *partition_changed, @@ -5488,8 +5458,7 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt) char shadow_path[FN_LEN]; DBUG_ENTER("write_log_drop_shadow_frm"); - build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt); pthread_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, NULL, (const char*)shadow_path, FALSE)) @@ -5537,8 +5506,7 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0); - build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt); pthread_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE)) goto error; @@ -5703,8 +5671,7 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0); - build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, lpt->alter_info->flags & ALTER_REORGANIZE_PARTITION)) @@ -5996,8 +5963,6 @@ void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, alter_info ALTER TABLE info create_info Create info for CREATE TABLE table_list List of the table involved - create_list The fields in the resulting table - key_list The keys in the resulting table db Database name of new table table_name Table name of new table @@ -6011,11 +5976,10 @@ void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, */ uint fast_alter_partition_table(THD *thd, TABLE *table, - ALTER_INFO *alter_info, + Alter_info *alter_info, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, - List<create_field> *create_list, - List<Key> *key_list, char *db, + char *db, const char *table_name, uint fast_alter_partition) { @@ -6032,8 +5996,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->part_info= part_info; lpt->alter_info= alter_info; lpt->create_info= create_info; - lpt->create_list= create_list; - lpt->key_list= key_list; lpt->db_options= create_info->table_options; if (create_info->row_type == ROW_TYPE_DYNAMIC) lpt->db_options|= HA_OPTION_PACK_RECORD; @@ -6111,7 +6073,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, The first approach here was to downgrade locks. Now a different approach is decided upon. The idea is that the handler will have access to the - ALTER_INFO when store_lock arrives with TL_WRITE_ALLOW_READ. So if the + Alter_info when store_lock arrives with TL_WRITE_ALLOW_READ. So if the handler knows that this functionality can be handled with a lower lock level it will set the lock level to TL_WRITE_ALLOW_WRITE immediately. Thus the need to downgrade the lock disappears. @@ -6384,7 +6346,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, user */ DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted, - table, table_list, FALSE, lpt, + table, table_list, FALSE, NULL, written_bin_log)); } #endif @@ -6408,8 +6370,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, also for other programs. */ -void set_field_ptr(Field **ptr, const byte *new_buf, - const byte *old_buf) +void set_field_ptr(Field **ptr, const uchar *new_buf, + const uchar *old_buf) { my_ptrdiff_t diff= (new_buf - old_buf); DBUG_ENTER("set_field_ptr"); @@ -6442,8 +6404,8 @@ void set_field_ptr(Field **ptr, const byte *new_buf, also for other programs. */ -void set_key_field_ptr(KEY *key_info, const byte *new_buf, - const byte *old_buf) +void set_key_field_ptr(KEY *key_info, const uchar *new_buf, + const uchar *old_buf) { KEY_PART_INFO *key_part= key_info->key_part; uint key_parts= key_info->key_parts; @@ -6694,7 +6656,7 @@ typedef uint32 (*get_endpoint_func)(partition_info*, bool left_endpoint, int get_part_iter_for_interval_via_mapping(partition_info *part_info, bool is_subpart, - char *min_value, char *max_value, + uchar *min_value, uchar *max_value, uint flags, PARTITION_ITERATOR *part_iter) { @@ -6850,7 +6812,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, int get_part_iter_for_interval_via_walking(partition_info *part_info, bool is_subpart, - char *min_value, char *max_value, + uchar *min_value, uchar *max_value, uint flags, PARTITION_ITERATOR *part_iter) { diff --git a/sql/sql_partition.h b/sql/sql_partition.h index e0c0f1c5bd3..d0c66083768 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -56,11 +56,11 @@ bool check_reorganise_list(partition_info *new_part_info, partition_info *old_part_info, List<char> list_part_names); handler *get_ha_partition(partition_info *part_info); -int get_parts_for_update(const byte *old_data, byte *new_data, - const byte *rec0, partition_info *part_info, +int get_parts_for_update(const uchar *old_data, uchar *new_data, + const uchar *rec0, partition_info *part_info, uint32 *old_part_id, uint32 *new_part_id, longlong *func_value); -int get_part_for_delete(const byte *buf, const byte *rec0, +int get_part_for_delete(const uchar *buf, const uchar *rec0, partition_info *part_info, uint32 *part_id); void prune_partition_set(const TABLE *table, part_id_range *part_spec); bool check_partition_info(partition_info *part_info,handlerton **eng_type, @@ -70,10 +70,10 @@ char *generate_partition_syntax(partition_info *part_info, uint *buf_length, bool use_sql_alloc, bool show_partition_options); bool partition_key_modified(TABLE *table, const MY_BITMAP *fields); -void get_partition_set(const TABLE *table, byte *buf, const uint index, +void get_partition_set(const TABLE *table, uchar *buf, const uint index, const key_range *key_spec, part_id_range *part_spec); -void get_full_part_id_from_key(const TABLE *table, byte *buf, +void get_full_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, part_id_range *part_spec); @@ -201,7 +201,7 @@ typedef struct st_partition_iter typedef int (*get_partitions_in_range_iter)(partition_info *part_info, bool is_subpart, - char *min_val, char *max_val, + uchar *min_val, uchar *max_val, uint flags, PARTITION_ITERATOR *part_iter); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 5f8513a4a9e..a44e20b8daf 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -177,9 +177,9 @@ public: { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; } bool check_update_type(Item_result type); SHOW_TYPE show_type(); - byte* real_value_ptr(THD *thd, enum_var_type type); + uchar* real_value_ptr(THD *thd, enum_var_type type); TYPELIB* plugin_var_typelib(void); - byte* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); bool update(THD *thd, set_var *var); @@ -210,6 +210,11 @@ static void reap_plugins(void); /* declared in set_var.cc */ extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error); +#ifdef EMBEDDED_LIBRARY +/* declared in sql_base.cc */ +extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); +#endif /* EMBEDDED_LIBRARY */ + /**************************************************************************** Value type thunks, allows the C world to play in the C++ world @@ -278,7 +283,7 @@ static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl) DBUG_ENTER("plugin_dl_find"); for (i= 0; i < plugin_dl_array.elements; i++) { - tmp= dynamic_element(&plugin_dl_array, 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, @@ -296,17 +301,20 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) DBUG_ENTER("plugin_dl_insert_or_reuse"); for (i= 0; i < plugin_dl_array.elements; i++) { - tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); + tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **); if (! tmp->ref_count) { memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl)); DBUG_RETURN(tmp); } } - if (insert_dynamic(&plugin_dl_array, (gptr)plugin_dl)) + if (insert_dynamic(&plugin_dl_array, (uchar*)&plugin_dl)) DBUG_RETURN(0); - DBUG_RETURN(dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1, - struct st_plugin_dl *)); + tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1, + struct st_plugin_dl **)= + (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (uchar*)plugin_dl, + sizeof(struct st_plugin_dl)); + DBUG_RETURN(tmp); } #endif /* HAVE_DLOPEN */ @@ -319,7 +327,7 @@ static inline void free_plugin_mem(struct st_plugin_dl *p) #endif my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR)); if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION) - my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); } @@ -471,7 +479,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) /* 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)))) + if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0)))) { free_plugin_mem(&plugin_dl); if (report & REPORT_TO_USER) @@ -516,8 +524,8 @@ static void plugin_dl_del(const LEX_STRING *dl) for (i= 0; i < plugin_dl_array.elements; i++) { - struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, - struct st_plugin_dl *); + 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, @@ -551,14 +559,14 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) { struct st_plugin_int *plugin= (st_plugin_int *) - hash_search(&plugin_hash[i], (const byte *)name->str, name->length); + hash_search(&plugin_hash[i], (const uchar *)name->str, name->length); if (plugin) DBUG_RETURN(plugin); } } else DBUG_RETURN((st_plugin_int *) - hash_search(&plugin_hash[type], (const byte *)name->str, name->length)); + hash_search(&plugin_hash[type], (const uchar *)name->str, name->length)); DBUG_RETURN(0); } @@ -628,7 +636,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) (long) current_thd, pi->name.str, pi->ref_count)); if (lex) - insert_dynamic(&lex->plugins, (gptr)&plugin); + insert_dynamic(&lex->plugins, (uchar*)&plugin); DBUG_RETURN(plugin); } DBUG_RETURN(NULL); @@ -665,21 +673,24 @@ plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) { uint i; + struct st_plugin_int *tmp; DBUG_ENTER("plugin_insert_or_reuse"); for (i= 0; i < plugin_array.elements; i++) { - struct st_plugin_int *tmp= dynamic_element(&plugin_array, i, - struct st_plugin_int *); + tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **); if (tmp->state == PLUGIN_IS_FREED) { memcpy(tmp, plugin, sizeof(struct st_plugin_int)); DBUG_RETURN(tmp); } } - if (insert_dynamic(&plugin_array, (gptr)plugin)) + if (insert_dynamic(&plugin_array, (uchar*)&plugin)) DBUG_RETURN(0); - DBUG_RETURN(dynamic_element(&plugin_array, plugin_array.elements - 1, - struct st_plugin_int *)); + tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1, + struct st_plugin_int **)= + (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)plugin, + sizeof(struct st_plugin_int)); + DBUG_RETURN(tmp); } @@ -737,13 +748,12 @@ static bool plugin_add(MEM_ROOT *tmp_root, tmp.name.length= name_len; tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; - if (!test_plugin_options(tmp_root, &tmp, argc, argv, true)) { if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) { plugin_array_version++; - if (!my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr)) + if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) { init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); DBUG_RETURN(FALSE); @@ -832,7 +842,7 @@ static void plugin_del(struct st_plugin_int *plugin) safe_mutex_assert_owner(&LOCK_plugin); /* Free allocated strings before deleting the plugin. */ plugin_vars_free_values(plugin->system_vars); - hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin); + hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); if (plugin->plugin_dl) plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; @@ -874,7 +884,7 @@ static void reap_plugins(void) for (idx= 0; idx < count; idx++) { - plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count) { /* change the status flag to prevent reaping by another thread */ @@ -914,7 +924,7 @@ static void intern_plugin_unlock(LEX *lex, plugin_ref plugin) if (!pi->plugin_dl) DBUG_VOID_RETURN; #else - my_free((gptr) plugin, MYF(MY_WME)); + my_free((uchar*) plugin, MYF(MY_WME)); #endif DBUG_PRINT("info",("unlocking plugin, name= %s, ref_count= %d", @@ -1048,21 +1058,21 @@ err: } -static byte *get_hash_key(const byte *buff, uint *length, +static uchar *get_hash_key(const uchar *buff, size_t *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); + return((uchar *)plugin->name.str); } -static byte *get_bookmark_hash_key(const byte *buff, uint *length, +static uchar *get_bookmark_hash_key(const uchar *buff, size_t *length, my_bool not_used __attribute__((unused))) { struct st_bookmark *var= (st_bookmark *)buff; *length= var->name_len + 1; - return (byte*) var->key; + return (uchar*) var->key; } @@ -1097,9 +1107,9 @@ int plugin_init(int *argc, char **argv, int flags) pthread_mutex_init(&LOCK_plugin, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&plugin_dl_array, - sizeof(struct st_plugin_dl),16,16) || + sizeof(struct st_plugin_dl *),16,16) || my_init_dynamic_array(&plugin_array, - sizeof(struct st_plugin_int),16,16)) + sizeof(struct st_plugin_int *),16,16)) goto err; for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) @@ -1179,13 +1189,14 @@ int plugin_init(int *argc, char **argv, int flags) /* Now we initialize all remaining plugins */ + pthread_mutex_lock(&LOCK_plugin); reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*)); *(reap++)= NULL; for (i= 0; i < plugin_array.elements; i++) { - plugin_ptr= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **); if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED) { if (plugin_initialize(plugin_ptr)) @@ -1212,6 +1223,7 @@ int plugin_init(int *argc, char **argv, int flags) end: free_root(&tmp_root, MYF(0)); + DBUG_RETURN(0); err_unlock: @@ -1232,13 +1244,15 @@ static bool register_builtin(struct st_mysql_plugin *plugin, tmp->ref_count= 0; tmp->plugin_dl= 0; - if (insert_dynamic(&plugin_array, (gptr)tmp)) + if (insert_dynamic(&plugin_array, (uchar*)&tmp)) DBUG_RETURN(1); - *ptr= dynamic_element(&plugin_array, plugin_array.elements - 1, - struct st_plugin_int *); + *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1, + struct st_plugin_int **)= + (struct st_plugin_int *) memdup_root(&plugin_mem_root, (uchar*)tmp, + sizeof(struct st_plugin_int)); - if (my_hash_insert(&plugin_hash[plugin->type],(byte*) *ptr)) + if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -1298,6 +1312,9 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) READ_RECORD read_record_info; int error; THD *new_thd; +#ifdef EMBEDDED_LIBRARY + bool table_exists; +#endif /* EMBEDDED_LIBRARY */ DBUG_ENTER("plugin_load"); if (!(new_thd= new THD)) @@ -1310,10 +1327,24 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) new_thd->store_globals(); new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db_length= 5; - bzero((gptr)&tables, sizeof(tables)); + bzero((uchar*)&tables, sizeof(tables)); tables.alias= tables.table_name= (char*)"plugin"; tables.lock_type= TL_READ; tables.db= new_thd->db; + +#ifdef EMBEDDED_LIBRARY + /* + When building an embedded library, if the mysql.plugin table + does not exist, we silently ignore the missing table + */ + pthread_mutex_lock(&LOCK_open); + if (check_if_table_exists(new_thd, &tables, &table_exists)) + table_exists= FALSE; + pthread_mutex_unlock(&LOCK_open); + if (!table_exists) + goto end; +#endif /* EMBEDDED_LIBRARY */ + if (simple_open_n_lock_tables(new_thd, &tables)) { DBUG_PRINT("error",("Can't open plugin table")); @@ -1458,7 +1489,7 @@ void plugin_shutdown(void) reap_plugins(); for (i= free_slots= 0; i < count; i++) { - plugin= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **); switch (plugin->state) { case PLUGIN_IS_READY: plugin->state= PLUGIN_IS_DELETED; @@ -1490,7 +1521,7 @@ void plugin_shutdown(void) */ for (i= 0; i < count; i++) { - plugins[i]= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **); /* change the state to ensure no reaping races */ if (plugins[i]->state == PLUGIN_IS_DELETED) plugins[i]->state= PLUGIN_IS_DYING; @@ -1555,7 +1586,7 @@ void plugin_shutdown(void) count= plugin_dl_array.elements; dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count); for (i= 0; i < count; i++) - dl[i]= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); + dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **); for (i= 0; i < plugin_dl_array.elements; i++) free_plugin_mem(dl[i]); my_afree(dl); @@ -1672,7 +1703,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) table->use_all_columns(); table->field[0]->store(name->str, name->length, system_charset_info); if (! table->file->index_read_idx(table->record[0], 0, - (byte *)table->field[0]->ptr, HA_WHOLE_KEY, + (uchar *)table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { int error; @@ -1714,7 +1745,7 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, { for (idx= 0; idx < total; idx++) { - plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; } } @@ -1789,7 +1820,7 @@ typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong); #define SET_PLUGIN_VAR_RESOLVE(opt)\ *(mysql_sys_var_ptr_p*)&((opt)->resolve)= mysql_sys_var_ptr -typedef byte *(*mysql_sys_var_ptr_p)(void* a_thd, int offset); +typedef uchar *(*mysql_sys_var_ptr_p)(void* a_thd, int offset); /**************************************************************************** @@ -2102,7 +2133,7 @@ static st_bookmark *find_bookmark(const char *plugin, const char *name, varname[0]= flags & PLUGIN_VAR_TYPEMASK; result= (st_bookmark*) hash_search(&bookmark_hash, - (const byte*) varname, length - 1); + (const uchar*) varname, length - 1); my_afree(varname); return result; @@ -2170,10 +2201,10 @@ static st_bookmark *register_var(const char *plugin, const char *name, if (new_size > global_variables_dynamic_size) { - global_system_variables.dynamic_variables_ptr= + global_system_variables.dynamic_variables_ptr= (char*) my_realloc(global_system_variables.dynamic_variables_ptr, new_size, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); - max_system_variables.dynamic_variables_ptr= + max_system_variables.dynamic_variables_ptr= (char*) my_realloc(max_system_variables.dynamic_variables_ptr, new_size, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); /* @@ -2200,7 +2231,7 @@ static st_bookmark *register_var(const char *plugin, const char *name, result->version= global_system_variables.dynamic_variables_version; /* this should succeed because we have already checked if a dup exists */ - if (my_hash_insert(&bookmark_hash, (byte*) result)) + if (my_hash_insert(&bookmark_hash, (uchar*) result)) { fprintf(stderr, "failed to add placeholder to hash"); DBUG_ASSERT(0); @@ -2217,13 +2248,13 @@ static st_bookmark *register_var(const char *plugin, const char *name, If required, will sync with global variables if the requested variable has not yet been allocated in the current thread. */ -static byte *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) +static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) { DBUG_ASSERT(offset >= 0); DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head); if (!thd) - return (byte*) global_system_variables.dynamic_variables_ptr + offset; + return (uchar*) global_system_variables.dynamic_variables_ptr + offset; /* dynamic_variables_head points to the largest valid offset @@ -2235,7 +2266,7 @@ static byte *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) rw_rdlock(&LOCK_system_variables_hash); - thd->variables.dynamic_variables_ptr= + thd->variables.dynamic_variables_ptr= (char*) my_realloc(thd->variables.dynamic_variables_ptr, global_variables_dynamic_size, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); @@ -2293,10 +2324,10 @@ static byte *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) rw_unlock(&LOCK_system_variables_hash); } - return (byte*)thd->variables.dynamic_variables_ptr + offset; + return (uchar*)thd->variables.dynamic_variables_ptr + offset; } -static byte *mysql_sys_var_ptr(void* a_thd, int offset) +static uchar *mysql_sys_var_ptr(void* a_thd, int offset) { return intern_sys_var_ptr((THD *)a_thd, offset, true); } @@ -2397,7 +2428,7 @@ void plugin_thdvar_cleanup(THD *thd) { list= ((plugin_ref*) thd->lex->plugins.buffer) + idx - 1; DBUG_PRINT("info",("unlocking %d plugins", idx)); - while ((char*) list >= thd->lex->plugins.buffer) + while ((uchar*) list >= thd->lex->plugins.buffer) intern_plugin_unlock(NULL, *list--); } @@ -2484,7 +2515,7 @@ SHOW_TYPE sys_var_pluginvar::show_type() } -byte* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) +uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) { DBUG_ASSERT(thd || (type == OPT_GLOBAL)); if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) @@ -2494,7 +2525,7 @@ byte* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false); } - return *(byte**) (plugin_var+1); + return *(uchar**) (plugin_var+1); } @@ -2516,15 +2547,15 @@ TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) } -byte* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, +uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - byte* result; + uchar* result; result= real_value_ptr(thd, type); if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM) - result= (byte*) get_type(plugin_var_typelib(), *(ulong*)result); + result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result); else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET) { char buffer[STRING_BUFFER_USUAL_SIZE]; @@ -2542,9 +2573,9 @@ byte* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, str.append(','); } - result= (byte*) ""; + result= (uchar*) ""; if (str.length()) - result= (byte*) thd->strmake(str.ptr(), str.length()-1); + result= (uchar*) thd->strmake(str.ptr(), str.length()-1); } return result; } @@ -2799,7 +2830,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, options[0].arg_type= options[1].arg_type= NO_ARG; options[0].def_value= options[1].def_value= **enabled; options[0].value= options[0].u_max_value= - options[1].value= options[1].u_max_value= (gptr*) (name - 1); + options[1].value= options[1].u_max_value= (uchar**) (name - 1); options+= 2; /* @@ -2878,9 +2909,9 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, if (!opt->update) { opt->update= update_func_str; - if (!(opt->flags & PLUGIN_VAR_MEMALLOC)) + if (!(opt->flags & PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) { - opt->flags |= PLUGIN_VAR_READONLY; + opt->flags|= PLUGIN_VAR_READONLY; sql_print_warning("Server variable %s of plugin %s was forced " "to be read-only: string variable without " "update_func and PLUGIN_VAR_MEMALLOC flag", @@ -2924,7 +2955,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, optnamelen= namelen + optnamelen + 1; } else - optname= memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1); + optname= (char*) memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1); /* convert '_' to '-' */ for (p= optname; *p; p++) @@ -2945,10 +2976,10 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET) { if (opt->flags & PLUGIN_VAR_THDLOCAL) - options->value= options->u_max_value= (gptr*) + options->value= options->u_max_value= (uchar**) (global_system_variables.dynamic_variables_ptr + offset); else - options->value= options->u_max_value= *(gptr**) (opt + 1); + options->value= options->u_max_value= *(uchar***) (opt + 1); } options[1]= options[0]; @@ -3139,7 +3170,7 @@ void my_print_help_inc_plugins(my_option *main_options, uint size) if (initialized) for (uint idx= 0; idx < plugin_array.elements; idx++) { - p= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); if (!p->plugin->system_vars || !(opt= construct_help_options(&mem_root, p))) @@ -3148,16 +3179,16 @@ void my_print_help_inc_plugins(my_option *main_options, uint size) /* Only options with a non-NULL comment are displayed in help text */ for (;opt->id; opt++) if (opt->comment) - insert_dynamic(&all_options, (gptr) opt); + insert_dynamic(&all_options, (uchar*) opt); } for (;main_options->id; main_options++) - insert_dynamic(&all_options, (gptr) main_options); + insert_dynamic(&all_options, (uchar*) main_options); sort_dynamic(&all_options, (qsort_cmp) option_cmp); /* main_options now points to the empty option terminator */ - insert_dynamic(&all_options, (gptr) main_options); + insert_dynamic(&all_options, (uchar*) main_options); my_print_help((my_option*) all_options.buffer); my_print_variables((my_option*) all_options.buffer); diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 70ce21a64da..e8f2cb6ee5e 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -33,7 +33,8 @@ class sys_var; */ #define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \ SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \ - SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH + SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH, \ + SHOW_LONGLONG_STATUS #include <mysql/plugin.h> #undef SHOW_FUNC typedef enum enum_mysql_show_type SHOW_TYPE; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 21d0308a830..7badccd55d9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -229,7 +229,7 @@ find_prepared_statement(THD *thd, ulong id, const char *where) static bool send_prep_stmt(Prepared_statement *stmt, uint columns) { NET *net= &stmt->thd->net; - char buff[12]; + uchar buff[12]; uint tmp; DBUG_ENTER("send_prep_stmt"); @@ -572,6 +572,8 @@ void set_param_date(Item_param *param, uchar **pos, ulong len) static void set_param_str(Item_param *param, uchar **pos, ulong len) { ulong length= get_param_length(pos, len); + if (length > len) + length= len; param->set_str((const char *)*pos, length); *pos+= length; } @@ -742,6 +744,8 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, if (read_pos >= data_end) DBUG_RETURN(1); param->set_param_func(param, &read_pos, data_end - read_pos); + if (param->state == Item_param::NO_VALUE) + DBUG_RETURN(1); } } res= param->query_val_str(&str); @@ -778,6 +782,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, if (read_pos >= data_end) DBUG_RETURN(1); param->set_param_func(param, &read_pos, data_end - read_pos); + if (param->state == Item_param::NO_VALUE) + DBUG_RETURN(1); } } if (param->convert_str_value(stmt->thd)) @@ -860,6 +866,8 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query) client_param->length ? *client_param->length : client_param->buffer_length); + if (param->state == Item_param::NO_VALUE) + DBUG_RETURN(1); } } if (param->convert_str_value(thd)) @@ -902,6 +910,8 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, client_param->length ? *client_param->length : client_param->buffer_length); + if (param->state == Item_param::NO_VALUE) + DBUG_RETURN(1); } } res= param->query_val_str(&str); @@ -946,7 +956,7 @@ static bool insert_params_from_vars(Prepared_statement *stmt, Item_param *param= *it; varname= var_it++; entry= (user_var_entry*)hash_search(&stmt->thd->user_vars, - (byte*) varname->str, + (uchar*) varname->str, varname->length); if (param->set_from_user_var(stmt->thd, entry) || param->convert_str_value(stmt->thd)) @@ -981,6 +991,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, String buf; const String *val; uint32 length= 0; + THD *thd= stmt->thd; DBUG_ENTER("insert_params_from_vars"); @@ -991,34 +1002,20 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, { Item_param *param= *it; varname= var_it++; - if (get_var_with_binlog(stmt->thd, stmt->lex->sql_command, - *varname, &entry)) - DBUG_RETURN(1); - if (param->set_from_user_var(stmt->thd, entry)) + entry= (user_var_entry *) hash_search(&thd->user_vars, (uchar*) varname->str, + varname->length); + /* + We have to call the setup_one_conversion_function() here to set + the parameter's members that might be needed further + (e.g. value.cs_info.character_set_client is used in the query_val_str()). + */ + setup_one_conversion_function(thd, param, param->param_type); + if (param->set_from_user_var(thd, entry)) DBUG_RETURN(1); - /* Insert @'escaped-varname' instead of parameter in the query */ - if (entry) - { - char *start, *ptr; - buf.length(0); - if (buf.reserve(entry->name.length*2+3)) - DBUG_RETURN(1); + val= param->query_val_str(&buf); - start= ptr= buf.c_ptr_quick(); - *ptr++= '@'; - *ptr++= '\''; - ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci, - ptr, 0, entry->name.str, - entry->name.length); - *ptr++= '\''; - buf.length(ptr - start); - val= &buf; - } - else - val= &my_null_string; - - if (param->convert_str_value(stmt->thd)) + if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ if (query->replace(param->pos_in_query+length, 1, *val)) @@ -1077,7 +1074,7 @@ static bool mysql_test_insert(Prepared_statement *stmt, if (table_list->table) { // don't allocate insert_values - table_list->table->insert_values=(byte *)1; + table_list->table->insert_values=(uchar *)1; } if (mysql_prepare_insert(thd, table_list, table_list->table, @@ -1604,7 +1601,7 @@ static bool mysql_insert_select_prepare_tester(THD *thd) next_local; /* Skip first table, which is the table we are inserting in */ - first_select->table_list.first= (byte *) second_table; + first_select->table_list.first= (uchar *) second_table; thd->lex->select_lex.context.table_list= thd->lex->select_lex.context.first_name_resolution_table= second_table; @@ -1635,7 +1632,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, if (tables->table) { // don't allocate insert_values - tables->table->insert_values=(byte *)1; + tables->table->insert_values=(uchar *)1; } if (insert_precheck(stmt->thd, tables)) @@ -1650,7 +1647,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, &mysql_insert_select_prepare_tester, OPTION_SETUP_TABLES_DONE); /* revert changes made by mysql_insert_select_prepare_tester */ - lex->select_lex.table_list.first= (byte*) first_local_table; + lex->select_lex.table_list.first= (uchar*) first_local_table; return res; } @@ -1987,7 +1984,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len) */ if ((entry= (user_var_entry*)hash_search(&thd->user_vars, - (byte*)lex->prepared_stmt_code.str, + (uchar*)lex->prepared_stmt_code.str, lex->prepared_stmt_code.length)) && entry->value) { @@ -2016,7 +2013,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len) len= (needs_conversion ? var_value->length() * to_cs->mbmaxlen : var_value->length()); - if (!(query_str= alloc_root(thd->mem_root, len+1))) + if (!(query_str= (char*) alloc_root(thd->mem_root, len+1))) goto end; if (needs_conversion) @@ -2369,7 +2366,7 @@ void mysql_sql_stmt_execute(THD *thd) /* Query text for binary, general or slow log, if any of them is open */ String expanded_query; DBUG_ENTER("mysql_sql_stmt_execute"); - DBUG_PRINT("info", ("EXECUTE: %.*s\n", name->length, name->str)); + DBUG_PRINT("info", ("EXECUTE: %.*s\n", (int) name->length, name->str)); if (!(stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) { @@ -2430,7 +2427,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) /* First of all clear possible warnings from the previous command */ mysql_reset_thd_for_next_command(thd); - statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_fetch); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) DBUG_VOID_RETURN; @@ -2494,7 +2491,7 @@ void mysql_stmt_reset(THD *thd, char *packet) /* First of all clear possible warnings from the previous command */ mysql_reset_thd_for_next_command(thd); - statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_reset); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; @@ -2557,7 +2554,8 @@ void mysql_sql_stmt_close(THD *thd) { Prepared_statement* stmt; LEX_STRING *name= &thd->lex->prepared_stmt_name; - DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", name->length, name->str)); + DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", (int) name->length, + name->str)); if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) { @@ -2598,7 +2596,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) #endif DBUG_ENTER("mysql_stmt_get_longdata"); - statistic_increment(thd->status_var.com_stmt_send_long_data, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_send_long_data); #ifndef EMBEDDED_LIBRARY /* Minimal size of long data packet is 6 bytes */ if (packet_length <= MYSQL_LONG_DATA_HEADER) @@ -2802,7 +2800,7 @@ void Prepared_statement::cleanup_stmt() bool Prepared_statement::set_name(LEX_STRING *name_arg) { name.length= name_arg->length; - name.str= memdup_root(mem_root, (char*) name_arg->str, name_arg->length); + name.str= (char*) memdup_root(mem_root, name_arg->str, name_arg->length); return name.str == 0; } @@ -2849,7 +2847,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) However, it seems handy if com_stmt_prepare is increased always, no matter what kind of prepare is processed. */ - statistic_increment(thd->status_var.com_stmt_prepare, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_prepare); /* alloc_query() uses thd->memroot && thd->query, so we should call @@ -2870,12 +2868,11 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) Lex_input_stream lip(thd, thd->query, thd->query_length); lip.stmt_prepare_mode= TRUE; - thd->m_lip= &lip; lex_start(thd); - int err= MYSQLparse((void *)thd); - error= err || thd->is_fatal_error || - thd->net.report_error || init_param_array(this); + error= parse_sql(thd, &lip) || + thd->net.report_error || + init_param_array(this); /* While doing context analysis of the query (in check_prepared_statement) @@ -2972,7 +2969,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) Query_arena *old_stmt_arena; bool error= TRUE; - statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_execute); /* Check if we got an error when sending long data */ if (state == Query_arena::ERROR) @@ -3094,7 +3091,7 @@ error: bool Prepared_statement::deallocate() { /* We account deallocate in the same manner as mysql_stmt_close */ - statistic_increment(thd->status_var.com_stmt_close, &LOCK_status); + status_var_increment(thd->status_var.com_stmt_close); if (flags & (uint) IS_IN_USE) { my_error(ER_PS_NO_RECURSION, MYF(0)); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d68dcf81282..1616e895107 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -72,7 +72,7 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, int8store(buf+R_POS_OFFSET,position); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p,ident_len); - if (my_net_write(net, (char*)packet->ptr(), packet->length())) + if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) { *errmsg = "failed on my_net_write()"; DBUG_RETURN(-1); @@ -83,12 +83,13 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, static int send_file(THD *thd) { NET* net = &thd->net; - int fd = -1,bytes, error = 1; + int fd = -1, error = 1; + size_t bytes; char fname[FN_REFLEN+1]; const char *errmsg = 0; int old_timeout; unsigned long packet_len; - char buf[IO_SIZE]; // It's safe to alloc this + uchar buf[IO_SIZE]; // It's safe to alloc this DBUG_ENTER("send_file"); /* @@ -96,7 +97,7 @@ static int send_file(THD *thd) the job */ old_timeout= net->read_timeout; - net_set_read_timeout(net, thd->variables.net_wait_timeout); + my_net_set_read_timeout(net, thd->variables.net_wait_timeout); /* We need net_flush here because the client will not know it needs to send @@ -121,7 +122,7 @@ static int send_file(THD *thd) goto err; } - while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0) + while ((long) (bytes= my_read(fd, buf, IO_SIZE, MYF(0))) > 0) { if (my_net_write(net, buf, bytes)) { @@ -131,7 +132,7 @@ static int send_file(THD *thd) } end: - if (my_net_write(net, "", 0) || net_flush(net) || + if (my_net_write(net, (uchar*) "", 0) || net_flush(net) || (my_net_read(net) == packet_error)) { errmsg = "while negotiating file transfer close"; @@ -140,7 +141,7 @@ static int send_file(THD *thd) error = 0; err: - net_set_read_timeout(net, old_timeout); + my_net_set_read_timeout(net, old_timeout); if (fd >= 0) (void) my_close(fd, MYF(0)); if (errmsg) @@ -217,7 +218,8 @@ bool log_in_use(const char* log_name) if ((linfo = tmp->current_linfo)) { pthread_mutex_lock(&linfo->lock); - result = !bcmp(log_name, linfo->log_file_name, log_name_len); + result = !bcmp((uchar*) log_name, (uchar*) linfo->log_file_name, + log_name_len); pthread_mutex_unlock(&linfo->lock); if (result) break; @@ -480,7 +482,7 @@ impossible position"; int4store((char*) packet->ptr()+LOG_EVENT_MINIMAL_HEADER_LEN+ ST_CREATED_OFFSET+1, (ulong) 0); /* send it */ - if (my_net_write(net, (char*)packet->ptr(), packet->length())) + if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) { errmsg = "Failed on my_net_write()"; my_errno= ER_UNKNOWN_ERROR; @@ -538,7 +540,7 @@ impossible position"; else if ((*packet)[EVENT_TYPE_OFFSET+1] == STOP_EVENT) binlog_can_be_corrupted= FALSE; - if (my_net_write(net, (char*)packet->ptr(), packet->length())) + if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) { errmsg = "Failed on my_net_write()"; my_errno= ER_UNKNOWN_ERROR; @@ -651,7 +653,7 @@ impossible position"; if (read_packet) { thd->proc_info = "Sending binlog event to slave"; - if (my_net_write(net, (char*)packet->ptr(), packet->length()) ) + if (my_net_write(net, (uchar*) packet->ptr(), packet->length()) ) { errmsg = "Failed on my_net_write()"; my_errno= ER_UNKNOWN_ERROR; @@ -989,7 +991,7 @@ int reset_slave(THD *thd, MASTER_INFO* mi) Reset errors (the idea is that we forget about the old master). */ - mi->rli.clear_slave_error(); + mi->rli.clear_error(); mi->rli.clear_until_condition(); // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0 @@ -1261,7 +1263,7 @@ bool change_master(THD* thd, MASTER_INFO* mi) pthread_mutex_lock(&mi->rli.data_lock); mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */ /* Clear the errors, for a clean start */ - mi->rli.clear_slave_error(); + mi->rli.clear_error(); mi->rli.clear_until_condition(); /* If we don't write new coordinates to disk now, then old will remain in diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ab0437dd7b5..98620800434 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -49,15 +49,15 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b); static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key); static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, table_map used_tables); -static void choose_plan(JOIN *join,table_map join_tables); +static bool choose_plan(JOIN *join,table_map join_tables); static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd, table_map remaining_tables, uint idx, double record_count, double read_time); static void optimize_straight_join(JOIN *join, table_map join_tables); -static void greedy_search(JOIN *join, table_map remaining_tables, +static bool greedy_search(JOIN *join, table_map remaining_tables, uint depth, uint prune_level); -static void best_extension_by_limited_search(JOIN *join, +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, double record_count, double read_time, uint depth, @@ -69,14 +69,14 @@ static int join_tab_cmp_straight(const void* ptr1, const void* ptr2); TODO: 'find_best' is here only temporarily until 'greedy_search' is tested and approved. */ -static void find_best(JOIN *join,table_map rest_tables,uint index, +static bool find_best(JOIN *join,table_map rest_tables,uint index, double record_count,double read_time); static uint cache_record_length(JOIN *join,uint index); static double prev_record_reads(JOIN *join, uint idx, table_map found_ref); static bool get_best_combination(JOIN *join); static store_key *get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, - KEY_PART_INFO *key_part, char *key_buff, + KEY_PART_INFO *key_part, uchar *key_buff, uint maybe_null); static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); @@ -1304,7 +1304,7 @@ JOIN::optimize() for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next) { Item *item= *tmp_order->item; - if (item->walk(&Item::is_expensive_processor, 0, (byte*)0)) + if (item->walk(&Item::is_expensive_processor, 0, (uchar*)0)) { /* Force tmp table without sort */ need_tmp=1; simple_order=simple_group=0; @@ -1537,7 +1537,7 @@ JOIN::save_join_tab() { if (!join_tab_save && select_lex->master_unit()->uncacheable) { - if (!(join_tab_save= (JOIN_TAB*)thd->memdup((gptr) join_tab, + if (!(join_tab_save= (JOIN_TAB*)thd->memdup((uchar*) join_tab, sizeof(JOIN_TAB) * tables))) return 1; } @@ -2104,6 +2104,17 @@ JOIN::exec() thd->examined_row_count+= curr_join->examined_rows; DBUG_PRINT("counts", ("thd->examined_row_count: %lu", (ulong) thd->examined_row_count)); + + /* + With EXPLAIN EXTENDED we have to restore original ref_array + for a derived table which is always materialized. + Otherwise we would not be able to print the query correctly. + */ + if (items0 && + (thd->lex->describe & DESCRIBE_EXTENDED) && + select_lex->linkage == DERIVED_TABLE_TYPE) + set_items_ref_array(items0); + DBUG_VOID_RETURN; } @@ -2755,11 +2766,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (join->const_tables != join->tables) { optimize_keyuse(join, keyuse_array); - choose_plan(join, all_table_map & ~join->const_table_map); + if (choose_plan(join, all_table_map & ~join->const_table_map)) + DBUG_RETURN(TRUE); } else { - memcpy((gptr) join->best_positions,(gptr) join->positions, + memcpy((uchar*) join->best_positions,(uchar*) join->positions, sizeof(POSITION)*join->const_tables); join->best_read=1.0; } @@ -3380,7 +3392,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL; keyuse.null_rejecting= key_field->null_rejecting; keyuse.cond_guard= key_field->cond_guard; - VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); + VOID(insert_dynamic(keyuse_array,(uchar*) &keyuse)); } } } @@ -3447,7 +3459,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array, keyuse.used_tables=cond_func->key_item()->used_tables(); keyuse.optimize= 0; keyuse.keypart_map= 0; - VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); + VOID(insert_dynamic(keyuse_array,(uchar*) &keyuse)); } @@ -3662,7 +3674,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, (qsort_cmp) sort_keyuse); bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */ - VOID(insert_dynamic(keyuse,(gptr) &key_end)); + VOID(insert_dynamic(keyuse,(uchar*) &key_end)); use=save_pos=dynamic_element(keyuse,0,KEYUSE*); prev= &key_end; @@ -3697,7 +3709,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, save_pos++; } i=(uint) (save_pos-(KEYUSE*) keyuse->buffer); - VOID(set_dynamic(keyuse,(gptr) &key_end,i)); + VOID(set_dynamic(keyuse,(uchar*) &key_end,i)); keyuse->elements=i; } return FALSE; @@ -3778,7 +3790,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) { /* Collect all query fields referenced in the GROUP clause. */ for (cur_group= join->group_list; cur_group; cur_group= cur_group->next) (*cur_group->item)->walk(&Item::collect_item_field_processor, 0, - (byte*) &indexed_fields); + (uchar*) &indexed_fields); } else if (join->select_distinct) { /* Collect all query fields referenced in the SELECT clause. */ @@ -3787,7 +3799,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) Item *item; while ((item= select_items_it++)) item->walk(&Item::collect_item_field_processor, 0, - (byte*) &indexed_fields); + (uchar*) &indexed_fields); } else return; @@ -4404,11 +4416,12 @@ best_access_path(JOIN *join, the array 'join->best_positions', and the cost of the plan in 'join->best_read'. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool choose_plan(JOIN *join, table_map join_tables) { uint search_depth= join->thd->variables.optimizer_search_depth; @@ -4441,14 +4454,16 @@ choose_plan(JOIN *join, table_map join_tables) the greedy version. Will be removed when greedy_search is approved. */ join->best_read= DBL_MAX; - find_best(join, join_tables, join->const_tables, 1.0, 0.0); + if (find_best(join, join_tables, join->const_tables, 1.0, 0.0)) + DBUG_RETURN(TRUE); } else { if (search_depth == 0) /* Automatically determine a reasonable value for 'search_depth' */ search_depth= determine_search_depth(join); - greedy_search(join, join_tables, search_depth, prune_level); + if (greedy_search(join, join_tables, search_depth, prune_level)) + DBUG_RETURN(TRUE); } } @@ -4456,7 +4471,7 @@ choose_plan(JOIN *join, table_map join_tables) Store the cost of this query into a user variable */ join->thd->status_var.last_query_cost= join->best_read; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -4608,7 +4623,7 @@ optimize_straight_join(JOIN *join, table_map join_tables) if (join->sort_by_table && join->sort_by_table != join->positions[join->const_tables].table->table) read_time+= record_count; // We have to make a temp table - memcpy((gptr) join->best_positions, (gptr) join->positions, + memcpy((uchar*) join->best_positions, (uchar*) join->positions, sizeof(POSITION)*idx); join->best_read= read_time; } @@ -4684,11 +4699,12 @@ optimize_straight_join(JOIN *join, table_map join_tables) In the future, 'greedy_search' might be extended to support other implementations of 'best_extension', e.g. some simpler quadratic procedure. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool greedy_search(JOIN *join, table_map remaining_tables, uint search_depth, @@ -4710,8 +4726,9 @@ greedy_search(JOIN *join, do { /* Find the extension of the current QEP with the lowest cost */ join->best_read= DBL_MAX; - best_extension_by_limited_search(join, remaining_tables, idx, record_count, - read_time, search_depth, prune_level); + if (best_extension_by_limited_search(join, remaining_tables, idx, record_count, + read_time, search_depth, prune_level)) + DBUG_RETURN(TRUE); if (size_remain <= search_depth) { @@ -4722,7 +4739,7 @@ greedy_search(JOIN *join, DBUG_EXECUTE("opt", print_plan(join, join->tables, record_count, read_time, read_time, "optimal");); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* select the first table in the optimal extension as most promising */ @@ -4867,11 +4884,12 @@ greedy_search(JOIN *join, The parameter 'search_depth' provides control over the recursion depth, and thus the size of the resulting optimal plan. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, @@ -4880,11 +4898,12 @@ best_extension_by_limited_search(JOIN *join, uint search_depth, uint prune_level) { + DBUG_ENTER("best_extension_by_limited_search"); + THD *thd= join->thd; if (thd->killed) // Abort - return; + DBUG_RETURN(TRUE); - DBUG_ENTER("best_extension_by_limited_search"); DBUG_EXECUTE("opt", print_plan(join, idx, read_time, record_count, idx, "SOFAR:");); @@ -4966,15 +4985,14 @@ best_extension_by_limited_search(JOIN *join, if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) ) { /* Recursively expand the current partial plan */ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - best_extension_by_limited_search(join, - remaining_tables & ~real_table_bit, - idx + 1, - current_record_count, - current_read_time, - search_depth - 1, - prune_level); - if (thd->killed) - DBUG_VOID_RETURN; + if (best_extension_by_limited_search(join, + remaining_tables & ~real_table_bit, + idx + 1, + current_record_count, + current_read_time, + search_depth - 1, + prune_level)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } else @@ -4990,7 +5008,7 @@ best_extension_by_limited_search(JOIN *join, current_read_time+= current_record_count; if ((search_depth == 1) || (current_read_time < join->best_read)) { - memcpy((gptr) join->best_positions, (gptr) join->positions, + memcpy((uchar*) join->best_positions, (uchar*) join->positions, sizeof(POSITION) * (idx + 1)); join->best_read= current_read_time - 0.001; } @@ -5003,19 +5021,26 @@ best_extension_by_limited_search(JOIN *join, restore_prev_nj_state(s); } } - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* TODO: this function is here only temporarily until 'greedy_search' is tested and accepted. + + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) { + DBUG_ENTER("find_best"); THD *thd= join->thd; + if (thd->killed) + DBUG_RETURN(TRUE); if (!rest_tables) { DBUG_PRINT("best",("read_time: %g record_count: %g",read_time, @@ -5028,14 +5053,14 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, read_time+=record_count; // We have to make a temp table if (read_time < join->best_read) { - memcpy((gptr) join->best_positions,(gptr) join->positions, + memcpy((uchar*) join->best_positions,(uchar*) join->positions, sizeof(POSITION)*idx); join->best_read= read_time - 0.001; } - return; + DBUG_RETURN(FALSE); } if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read) - return; /* Found better before */ + DBUG_RETURN(FALSE); /* Found better before */ JOIN_TAB *s; double best_record_count=DBL_MAX,best_read_time=DBL_MAX; @@ -5068,10 +5093,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, best_read_time=current_read_time; } swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - find_best(join,rest_tables & ~real_table_bit,idx+1, - current_record_count,current_read_time); - if (thd->killed) - return; + if (find_best(join,rest_tables & ~real_table_bit,idx+1, + current_record_count,current_read_time)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } restore_prev_nj_state(s); @@ -5079,6 +5103,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, break; // Don't test all combinations } } + DBUG_RETURN(FALSE); } @@ -5339,7 +5364,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, j->ref.key_parts=keyparts; j->ref.key_length=length; j->ref.key=(int) key; - if (!(j->ref.key_buff= (byte*) thd->calloc(ALIGN_SIZE(length)*2)) || + if (!(j->ref.key_buff= (uchar*) thd->calloc(ALIGN_SIZE(length)*2)) || !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) * (keyparts+1)))) || !(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)) || @@ -5353,7 +5378,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, keyuse=org_keyuse; store_key **ref_key= j->ref.key_copy; - byte *key_buff=j->ref.key_buff, *null_ref_key= 0; + uchar *key_buff=j->ref.key_buff, *null_ref_key= 0; bool keyuse_uses_no_tables= TRUE; if (ftkey) { @@ -5384,8 +5409,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, !(join->select_options & SELECT_DESCRIBE)) { // Compare against constant store_key_item tmp(thd, keyinfo->key_part[i].field, - (char*)key_buff + maybe_null, - maybe_null ? (char*) key_buff : 0, + key_buff + maybe_null, + maybe_null ? key_buff : 0, keyinfo->key_part[i].length, keyuse->val); if (thd->is_fatal_error) DBUG_RETURN(TRUE); @@ -5395,7 +5420,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, *ref_key++= get_store_key(thd, keyuse,join->const_table_map, &keyinfo->key_part[i], - (char*) key_buff,maybe_null); + key_buff, maybe_null); /* Remember if we are going to use REF_OR_NULL But only if field _really_ can be null i.e. we force JT_REF @@ -5439,7 +5464,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, static store_key * get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, - KEY_PART_INFO *key_part, char *key_buff, uint maybe_null) + KEY_PART_INFO *key_part, uchar *key_buff, uint maybe_null) { if (!((~used_tables) & keyuse->used_tables)) // if const item { @@ -5938,7 +5963,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { DBUG_EXECUTE("where",print_where(tmp,tab->table->alias);); SQL_SELECT *sel= tab->select= ((SQL_SELECT*) - thd->memdup((gptr) select, + thd->memdup((uchar*) select, sizeof(*select))); if (!sel) DBUG_RETURN(1); // End of memory @@ -6090,7 +6115,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { DBUG_EXECUTE("where",print_where(tmp,"cache");); tab->cache.select=(SQL_SELECT*) - thd->memdup((gptr) sel, sizeof(SQL_SELECT)); + thd->memdup((uchar*) sel, sizeof(SQL_SELECT)); tab->cache.select->cond=tmp; tab->cache.select->read_tables=join->const_table_map; } @@ -6099,13 +6124,39 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } /* - Push down all predicates from on expressions. - Each of these predicated are guarded by a variable + Push down conditions from all on expressions. + Each of these conditions are guarded by a variable that turns if off just before null complemented row for - outer joins is formed. Thus, the predicates from an + outer joins is formed. Thus, the condition from an 'on expression' are guaranteed not to be checked for the null complemented row. */ + + /* First push down constant conditions from on expressions */ + for (JOIN_TAB *join_tab= join->join_tab+join->const_tables; + join_tab < join->join_tab+join->tables ; join_tab++) + { + if (*join_tab->on_expr_ref) + { + JOIN_TAB *cond_tab= join_tab->first_inner; + COND *tmp= make_cond_for_table(*join_tab->on_expr_ref, + join->const_table_map, + (table_map) 0); + if (!tmp) + continue; + tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl); + if (!tmp) + DBUG_RETURN(1); + tmp->quick_fix_field(); + cond_tab->select_cond= !cond_tab->select_cond ? tmp : + new Item_cond_and(cond_tab->select_cond,tmp); + if (!cond_tab->select_cond) + DBUG_RETURN(1); + cond_tab->select_cond->quick_fix_field(); + } + } + + /* Push down non-constant conditions from on expressions */ JOIN_TAB *last_tab= tab; while (first_inner_tab && first_inner_tab->last_inner == last_tab) { @@ -6288,8 +6339,7 @@ make_join_readinfo(JOIN *join, ulonglong options) join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED; tab->read_first_record= join_init_quick_read_record; if (statistics) - statistic_increment(join->thd->status_var.select_range_check_count, - &LOCK_status); + status_var_increment(join->thd->status_var.select_range_check_count); } else { @@ -6299,15 +6349,13 @@ make_join_readinfo(JOIN *join, ulonglong options) if (tab->select && tab->select->quick) { if (statistics) - statistic_increment(join->thd->status_var.select_range_count, - &LOCK_status); + status_var_increment(join->thd->status_var.select_range_count); } else { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; if (statistics) - statistic_increment(join->thd->status_var.select_scan_count, - &LOCK_status); + status_var_increment(join->thd->status_var.select_scan_count); } } else @@ -6315,15 +6363,13 @@ make_join_readinfo(JOIN *join, ulonglong options) if (tab->select && tab->select->quick) { if (statistics) - statistic_increment(join->thd->status_var.select_full_range_join_count, - &LOCK_status); + status_var_increment(join->thd->status_var.select_full_range_join_count); } else { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; if (statistics) - statistic_increment(join->thd->status_var.select_full_join_count, - &LOCK_status); + status_var_increment(join->thd->status_var.select_full_join_count); } } if (!table->no_keyread) @@ -6558,7 +6604,6 @@ void JOIN::cleanup(bool full) for (tab= join_tab, end= tab+tables; tab != end; tab++) tab->cleanup(); table= 0; - tables= 0; } else { @@ -7532,11 +7577,11 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, as soon the field is not of a string type or the field reference is an argument of a comparison predicate. */ - byte *is_subst_valid= (byte *) 1; + uchar *is_subst_valid= (uchar *) 1; cond= cond->compile(&Item::subst_argument_checker, &is_subst_valid, &Item::equal_fields_propagator, - (byte *) inherited); + (uchar *) inherited); cond->update_used_tables(); } return cond; @@ -8997,7 +9042,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, Make sure that the blob fits into a Field_varstring which has 2-byte lenght. */ - if (convert_blob_length && convert_blob_length < UINT_MAX16 && + if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE && (org_field->flags & BLOB_FLAG)) new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(), @@ -9065,8 +9110,13 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->name, item->decimals, TRUE); break; case INT_RESULT: - /* Select an integer type with the minimal fit precision */ - if (item->max_length > MY_INT32_NUM_DECIMAL_DIGITS) + /* + Select an integer type with the minimal fit precision. + MY_INT32_NUM_DECIMAL_DIGITS is sign inclusive, don't consider the sign. + Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into + Field_long : make them Field_longlong. + */ + if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1)) new_field=new Field_longlong(item->max_length, maybe_null, item->name, item->unsigned_flag); else @@ -9090,7 +9140,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, 2-byte lenght. */ else if (item->max_length/item->collation.collation->mbmaxlen > 255 && - convert_blob_length < UINT_MAX16 && convert_blob_length) + convert_blob_length <= Field_varstring::MAX_SIZE && + convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, item->name, table->s, item->collation.collation); @@ -9295,7 +9346,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, a tmp_set bitmap to be used by things like filesort. */ -void setup_tmp_table_column_bitmaps(TABLE *table, byte *bitmaps) +void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps) { uint field_count= table->s->fields; bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count, @@ -9364,8 +9415,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, bool using_unique_constraint= 0; bool use_packed_rows= 0; bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS); - char *tmpname,path[FN_REFLEN]; - byte *pos, *group_buff, *bitmaps; + char *tmpname, *tmppath, path[FN_REFLEN], table_name[NAME_LEN+1]; + uchar *pos, *group_buff, *bitmaps; uchar *null_flags; Field **reg_field, **from_field, **default_field; uint *blob_field; @@ -9382,18 +9433,18 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, (int) distinct, (int) save_sum_fields, (ulong) rows_limit,test(group))); - statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status); + status_var_increment(thd->status_var.created_tmp_tables); if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) temp_pool_slot = bitmap_lock_set_next(&temp_pool); if (temp_pool_slot != MY_BIT_NONE) // we got a slot - sprintf(path, "%s_%lx_%i", tmp_file_prefix, - current_pid, temp_pool_slot); + sprintf(table_name, "%s_%lx_%i", tmp_file_prefix, + current_pid, temp_pool_slot); else { /* if we run out of slots or we are not using tempool */ - sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid, + sprintf(table_name, "%s%lx_%lx_%x", tmp_file_prefix,current_pid, thd->thread_id, thd->tmp_table++); } @@ -9401,7 +9452,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, No need to change table name to lower case as we are only creating MyISAM or HEAP tables here */ - fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); + fn_format(path, table_name, mysql_tmpdir, "", + MY_REPLACE_EXT|MY_UNPACK_FILENAME); if (group) { @@ -9447,7 +9499,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, sizeof(*key_part_info)*(param->group_parts+1), ¶m->start_recinfo, sizeof(*param->recinfo)*(field_count*2+4), - &tmpname, (uint) strlen(path)+1, + &tmppath, (uint) strlen(path)+1, + &tmpname, (uint) strlen(table_name)+1, &group_buff, (group && ! using_unique_constraint ? param->group_length : 0), &bitmaps, bitmap_buffer_size(field_count)*2, @@ -9466,7 +9519,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, DBUG_RETURN(NULL); /* purecov: inspected */ } param->items_to_copy= copy_func; - strmov(tmpname,path); + strmov(tmppath, path); + strmov(tmpname, table_name); /* make table according to fields */ bzero((char*) table,sizeof(*table)); @@ -9491,7 +9545,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->keys_in_use_for_query.init(); table->s= share; - init_tmp_table_share(share, "", 0, tmpname, tmpname); + init_tmp_table_share(share, "", 0, tmpname, tmppath); share->blob_field= blob_field; share->blob_ptr_size= mi_portable_sizeof_char_ptr; share->db_low_byte_first=1; // True for HEAP and MyISAM @@ -9709,7 +9763,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, { uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1); share->rec_buff_length= alloc_length; - if (!(table->record[0]= (byte*) + if (!(table->record[0]= (uchar*) alloc_root(&table->mem_root, alloc_length*3))) goto err; table->record[1]= table->record[0]+alloc_length; @@ -9725,7 +9779,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, pos=table->record[0]+ null_pack_length; if (null_pack_length) { - bzero((byte*) recinfo,sizeof(*recinfo)); + bzero((uchar*) recinfo,sizeof(*recinfo)); recinfo->type=FIELD_NORMAL; recinfo->length=null_pack_length; recinfo++; @@ -9741,7 +9795,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, { Field *field= *reg_field; uint length; - bzero((byte*) recinfo,sizeof(*recinfo)); + bzero((uchar*) recinfo,sizeof(*recinfo)); if (!(field->flags & NOT_NULL_FLAG)) { @@ -9755,19 +9809,19 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, recinfo->length=1; recinfo->type=FIELD_NORMAL; recinfo++; - bzero((byte*) recinfo,sizeof(*recinfo)); + bzero((uchar*) recinfo,sizeof(*recinfo)); } else { recinfo->null_bit= 1 << (null_count & 7); recinfo->null_pos= null_count/8; } - field->move_field((char*) pos,null_flags+null_count/8, + field->move_field(pos,null_flags+null_count/8, 1 << (null_count & 7)); null_count++; } else - field->move_field((char*) pos,(uchar*) 0,0); + field->move_field(pos,(uchar*) 0,0); if (field->type() == MYSQL_TYPE_BIT) { /* We have to reserve place for extra bits among null bits */ @@ -9885,10 +9939,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, { cur_group->buff=(char*) group_buff; if (!(cur_group->field= field->new_key_field(thd->mem_root,table, - (char*) group_buff + - test(maybe_null), - field->null_ptr, - field->null_bit))) + group_buff + + test(maybe_null), + field->null_ptr, + field->null_bit))) goto err; /* purecov: inspected */ if (maybe_null) { @@ -9950,7 +10004,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, key_part_info->null_bit=0; key_part_info->offset=hidden_null_pack_length; key_part_info->length=null_pack_length; - key_part_info->field= new Field_string((char*) table->record[0], + key_part_info->field= new Field_string(table->record[0], (uint32) key_part_info->length, (uchar*) 0, (uint) 0, @@ -10029,17 +10083,17 @@ err: 0 if out of memory, TABLE object in case of success */ -TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) +TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list) { uint field_count= field_list.elements; uint blob_count= 0; Field **field; - create_field *cdef; /* column definition */ + Create_field *cdef; /* column definition */ uint record_length= 0; uint null_count= 0; /* number of columns which may be null */ uint null_pack_length; /* NULL representation array length */ uint *blob_field; - byte *bitmaps; + uchar *bitmaps; TABLE *table; TABLE_SHARE *share; @@ -10062,7 +10116,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) setup_tmp_table_column_bitmaps(table, bitmaps); /* Create all fields and calculate the total length of record */ - List_iterator_fast<create_field> it(field_list); + List_iterator_fast<Create_field> it(field_list); while ((cdef= it++)) { *field= make_field(share, 0, cdef->length, @@ -10090,7 +10144,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) null_pack_length= (null_count + 7)/8; share->reclength= record_length + null_pack_length; share->rec_buff_length= ALIGN_SIZE(share->reclength + 1); - table->record[0]= (byte*) thd->alloc(share->rec_buff_length); + table->record[0]= (uchar*) thd->alloc(share->rec_buff_length); if (!table->record[0]) goto error; @@ -10104,18 +10158,18 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) table->in_use= thd; /* field->reset() may access table->in_use */ { /* Set up field pointers */ - byte *null_pos= table->record[0]; - byte *field_pos= null_pos + share->null_bytes; + uchar *null_pos= table->record[0]; + uchar *field_pos= null_pos + share->null_bytes; uint null_bit= 1; for (field= table->field; *field; ++field) { Field *cur_field= *field; if ((cur_field->flags & NOT_NULL_FLAG)) - cur_field->move_field((char*) field_pos); + cur_field->move_field(field_pos); else { - cur_field->move_field((char*) field_pos, (uchar*) null_pos, null_bit); + cur_field->move_field(field_pos, (uchar*) null_pos, null_bit); null_bit<<= 1; if (null_bit == (1 << 8)) { @@ -10184,7 +10238,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, uniquedef.null_are_equal=1; /* Create extra column for hash value */ - bzero((byte*) param->recinfo,sizeof(*param->recinfo)); + bzero((uchar*) param->recinfo,sizeof(*param->recinfo)); param->recinfo->type= FIELD_CHECK; param->recinfo->length=MI_UNIQUE_HASH_LENGTH; param->recinfo++; @@ -10254,8 +10308,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, table->db_stat=0; goto err; } - statistic_increment(table->in_use->status_var.created_tmp_disk_tables, - &LOCK_status); + status_var_increment(table->in_use->status_var.created_tmp_disk_tables); share->db_record_offset= 1; DBUG_RETURN(0); err: @@ -10364,7 +10417,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, */ while (!table->file->rnd_next(new_table.record[1])) { - if ((write_err= new_table.file->write_row(new_table.record[1]))) + write_err= new_table.file->write_row(new_table.record[1]); + DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;); + if (write_err) goto err; } /* copy row that filled HEAP table */ @@ -10396,7 +10451,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, err: DBUG_PRINT("error",("Got error: %d",write_err)); - table->file->print_error(error,MYF(0)); // Give table is full error + table->file->print_error(write_err, MYF(0)); (void) table->file->ha_rnd_end(); (void) new_table.file->close(); err1: @@ -10404,6 +10459,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, err2: delete new_table.file; thd->proc_info=save_proc_info; + table->mem_root= new_table.mem_root; DBUG_RETURN(1); } @@ -11234,7 +11290,7 @@ join_read_const(JOIN_TAB *tab) else { error=table->file->index_read_idx(table->record[0],tab->ref.key, - (byte*) tab->ref.key_buff, + (uchar*) tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts), HA_READ_KEY_EXACT); } @@ -11811,7 +11867,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (item->maybe_null) { Field *field=item->get_tmp_table_field(); - field->ptr[-1]= (byte) (field->is_null() ? 1 : 0); + field->ptr[-1]= (uchar) (field->is_null() ? 1 : 0); } } } @@ -13000,7 +13056,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field, { handler *file=table->file; char *org_record,*new_record; - byte *record; + uchar *record; int error; ulong reclength= table->s->reclength-offset; DBUG_ENTER("remove_dup_with_compare"); @@ -13091,7 +13147,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, ulong key_length, Item *having) { - byte *key_buffer, *key_pos, *record=table->record[0]; + uchar *key_buffer, *key_pos, *record=table->record[0]; int error; handler *file= table->file; ulong extra_length= ALIGN_SIZE(key_length)-key_length; @@ -13135,7 +13191,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, key_pos=key_buffer; for (;;) { - byte *org_key_pos; + uchar *org_key_pos; if (thd->killed) { thd->send_kill_message(); @@ -13162,7 +13218,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, field_length=field_lengths; for (Field **ptr= first_field ; *ptr ; ptr++) { - (*ptr)->sort_string((char*) key_pos,*field_length); + (*ptr)->sort_string(key_pos,*field_length); key_pos+= *field_length++; } /* Check if it exists before */ @@ -13265,7 +13321,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count) sizeof(CACHE_FIELD*)))) { - my_free((gptr) cache->buff,MYF(0)); /* purecov: inspected */ + my_free((uchar*) cache->buff,MYF(0)); /* purecov: inspected */ cache->buff=0; /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } @@ -13298,7 +13354,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count) /* Copy null bits from table */ if (null_fields && tables[i].table->s->null_fields) { /* must copy null bits */ - copy->str=(char*) tables[i].table->null_flags; + copy->str= tables[i].table->null_flags; copy->length= tables[i].table->s->null_bytes; copy->strip=0; copy->blob_field=0; @@ -13309,7 +13365,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count) /* If outer join table, copy null_row flag */ if (tables[i].table->maybe_null) { - copy->str= (char*) &tables[i].table->null_row; + copy->str= (uchar*) &tables[i].table->null_row; copy->length=sizeof(tables[i].table->null_row); copy->strip=0; copy->blob_field=0; @@ -13372,13 +13428,13 @@ store_record_in_cache(JOIN_CACHE *cache) { if (last_record) { - copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), + copy->blob_field->get_image(pos, copy->length+sizeof(char*), copy->blob_field->charset()); pos+=copy->length+sizeof(char*); } else { - copy->blob_field->get_image((char*) pos,copy->length, // blob length + copy->blob_field->get_image(pos, copy->length, // blob length copy->blob_field->charset()); memcpy(pos+copy->length,copy->str,copy->blob_length); // Blob data pos+=copy->length+copy->blob_length; @@ -13388,7 +13444,7 @@ store_record_in_cache(JOIN_CACHE *cache) { if (copy->strip) { - char *str,*end; + uchar *str,*end; for (str=copy->str,end= str+copy->length; end > str && end[-1] == ' ' ; end--) ; @@ -13444,13 +13500,13 @@ read_cached_record(JOIN_TAB *tab) { if (last_record) { - copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*), + copy->blob_field->set_image(pos, copy->length+sizeof(char*), copy->blob_field->charset()); pos+=copy->length+sizeof(char*); } else { - copy->blob_field->set_ptr((char*) pos,(char*) pos+copy->length); + copy->blob_field->set_ptr(pos, pos+copy->length); pos+=copy->length+copy->blob_field->get_length(); } } @@ -14200,7 +14256,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, for (i= 0; (pos= li++); i++) { Field *field; - char *tmp; + uchar *tmp; Item *real_pos= pos->real_item(); if (real_pos->type() == Item::FIELD_ITEM) { @@ -14245,8 +14301,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, another extra byte to not get warnings from purify in Field_string::val_int */ - tmp= (char*) sql_alloc(field->pack_length()+2); - if (!tmp) + if (!(tmp= (uchar*) sql_alloc(field->pack_length()+2))) goto err; if (copy) { @@ -15538,8 +15593,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, break; } } - if (tab->next_select == sub_select_cache) - extra.append(STRING_WITH_LEN("; Using join cache")); + if (i > 0 && tab[-1].next_select == sub_select_cache) + extra.append(STRING_WITH_LEN("; Using join buffer")); /* Skip initial "; "*/ const char *str= extra.ptr(); diff --git a/sql/sql_select.h b/sql/sql_select.h index 971b7caf69d..290a0f5d992 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -56,8 +56,8 @@ typedef struct st_table_ref uint key_parts; // num of ... uint key_length; // length of key_buff int key; // key no - byte *key_buff; // value to look for with key - byte *key_buff2; // key_buff+key_length + uchar *key_buff; // value to look for with key + uchar *key_buff2; // key_buff+key_length store_key **key_copy; // Item **items; // val()'s for each keypart /* @@ -79,7 +79,7 @@ typedef struct st_table_ref key_part_map null_rejecting; table_map depend_map; // Table depends on these tables. /* null byte position in the key_buf. Used for REF_OR_NULL optimization */ - byte *null_ref_key; + uchar *null_ref_key; } TABLE_REF; @@ -89,8 +89,8 @@ typedef struct st_table_ref */ typedef struct st_cache_field { - char *str; - uint length,blob_length; + uchar *str; + uint length, blob_length; Field_blob *blob_field; bool strip; } CACHE_FIELD; @@ -538,20 +538,20 @@ class store_key :public Sql_alloc public: bool null_key; /* TRUE <=> the value of the key has a null part */ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; - store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) + store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length) :null_key(0), null_ptr(null), err(0) { if (field_arg->type() == MYSQL_TYPE_BLOB) { /* Key segments are always packed with a 2 byte length prefix */ - to_field= new Field_varstring(ptr, length, 2, (uchar*) null, 1, + to_field= new Field_varstring(ptr, length, 2, null, 1, Field::NONE, field_arg->field_name, field_arg->table->s, field_arg->charset()); to_field->init(field_arg->table); } else to_field=field_arg->new_key_field(thd->mem_root, field_arg->table, - ptr, (uchar*) null, 1); + ptr, null, 1); } virtual ~store_key() {} /* Not actually needed */ virtual const char *name() const=0; @@ -579,8 +579,8 @@ public: protected: Field *to_field; // Store data here - char *null_ptr; - char err; + uchar *null_ptr; + uchar err; virtual enum store_key_result copy_inner()=0; }; @@ -591,11 +591,12 @@ class store_key_field: public store_key Copy_field copy_field; const char *field_name; public: - store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg, + store_key_field(THD *thd, Field *to_field_arg, uchar *ptr, + uchar *null_ptr_arg, uint length, Field *from_field, const char *name_arg) :store_key(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err - : NullS,length), field_name(name_arg) + : (uchar*) 0, length), field_name(name_arg) { if (to_field) { @@ -623,11 +624,11 @@ class store_key_item :public store_key protected: Item *item; public: - store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg, - uint length, Item *item_arg) - :store_key(thd, to_field_arg,ptr, + store_key_item(THD *thd, Field *to_field_arg, uchar *ptr, + uchar *null_ptr_arg, uint length, Item *item_arg) + :store_key(thd, to_field_arg, ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? - &err : NullS, length), item(item_arg) + &err : (uchar*) 0, length), item(item_arg) {} const char *name() const { return "func"; } @@ -649,12 +650,12 @@ class store_key_const_item :public store_key_item { bool inited; public: - store_key_const_item(THD *thd, Field *to_field_arg, char *ptr, - char *null_ptr_arg, uint length, + store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr, + uchar *null_ptr_arg, uint length, Item *item_arg) :store_key_item(thd, to_field_arg,ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? - &err : NullS, length, item_arg), inited(0) + &err : (uchar*) 0, length, item_arg), inited(0) { } const char *name() const { return "const"; } diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index a62ce98850b..195e6743a72 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -77,7 +77,7 @@ static void merge_server_struct(FOREIGN_SERVER *from, FOREIGN_SERVER *to); -static byte *servers_cache_get_key(FOREIGN_SERVER *server, uint *length, +static uchar *servers_cache_get_key(FOREIGN_SERVER *server, size_t *length, my_bool not_used __attribute__((unused))) { DBUG_ENTER("servers_cache_get_key"); @@ -86,7 +86,7 @@ static byte *servers_cache_get_key(FOREIGN_SERVER *server, uint *length, server->server_name)); *length= (uint) server->server_name_length; - DBUG_RETURN((byte*) server->server_name); + DBUG_RETURN((uchar*) server->server_name); } @@ -323,7 +323,7 @@ get_server_from_table_to_cache(TABLE *table) DBUG_PRINT("info", ("server->username %s", server->username)); DBUG_PRINT("info", ("server->password %s", server->password)); DBUG_PRINT("info", ("server->socket %s", server->socket)); - if (my_hash_insert(&servers_cache, (byte*) server)) + if (my_hash_insert(&servers_cache, (uchar*) server)) { DBUG_PRINT("info", ("had a problem inserting server %s at %lx", server->server_name, (long unsigned int) server)); @@ -411,7 +411,7 @@ insert_server_record_into_cache(FOREIGN_SERVER *server) DBUG_PRINT("info", ("inserting server %s at %lx, length %d", server->server_name, (long unsigned int) server, server->server_name_length)); - if (my_hash_insert(&servers_cache, (byte*) server)) + if (my_hash_insert(&servers_cache, (uchar*) server)) { DBUG_PRINT("info", ("had a problem inserting server %s at %lx", server->server_name, (long unsigned int) server)); @@ -517,7 +517,7 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server) /* read index until record is that specified in server_name */ if ((error= table->file->index_read_idx(table->record[0], 0, - (byte *)table->field[0]->ptr, HA_WHOLE_KEY, + (uchar *)table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT))) { /* if not found, err */ @@ -642,7 +642,7 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options) if (!(server= (FOREIGN_SERVER *) hash_search(&servers_cache, - (byte*) server_options->server_name, + (uchar*) server_options->server_name, server_options->server_name_length))) { DBUG_PRINT("info", ("server_name %s length %d not found!", @@ -658,7 +658,7 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options) server->server_name, server->server_name_length)); - VOID(hash_delete(&servers_cache, (byte*) server)); + VOID(hash_delete(&servers_cache, (uchar*) server)); error= 0; @@ -765,12 +765,12 @@ int update_server_record_in_cache(FOREIGN_SERVER *existing, /* delete the existing server struct from the server cache */ - VOID(hash_delete(&servers_cache, (byte*)existing)); + VOID(hash_delete(&servers_cache, (uchar*)existing)); /* Insert the altered server struct into the server cache */ - if (my_hash_insert(&servers_cache, (byte*)altered)) + if (my_hash_insert(&servers_cache, (uchar*)altered)) { DBUG_PRINT("info", ("had a problem inserting server %s at %lx", altered->server_name, (long unsigned int) altered)); @@ -859,7 +859,7 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server) system_charset_info); if ((error= table->file->index_read_idx(table->record[0], 0, - (byte *)table->field[0]->ptr, ~(longlong)0, + (uchar *)table->field[0]->ptr, ~(longlong)0, HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) @@ -911,7 +911,7 @@ delete_server_record(TABLE *table, table->field[0]->store(server_name, server_name_length, system_charset_info); if ((error= table->file->index_read_idx(table->record[0], 0, - (byte *)table->field[0]->ptr, HA_WHOLE_KEY, + (uchar *)table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) @@ -954,7 +954,7 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options) rw_wrlock(&THR_LOCK_servers); /* hit the memory first */ - if (hash_search(&servers_cache, (byte*) server_options->server_name, + if (hash_search(&servers_cache, (uchar*) server_options->server_name, server_options->server_name_length)) goto end; @@ -1000,7 +1000,7 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) rw_wrlock(&THR_LOCK_servers); if (!(existing= (FOREIGN_SERVER *) hash_search(&servers_cache, - (byte*) name.str, + (uchar*) name.str, name.length))) goto end; @@ -1260,7 +1260,7 @@ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, DBUG_PRINT("info", ("locking servers_cache")); rw_rdlock(&THR_LOCK_servers); if (!(server= (FOREIGN_SERVER *) hash_search(&servers_cache, - (byte*) server_name, + (uchar*) server_name, server_name_length))) { DBUG_PRINT("info", ("server_name %s length %d not found!", diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e8107248c14..903c8ab74f1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -79,58 +79,6 @@ append_algorithm(TABLE_LIST *table, String *buff); ** List all table types supported ***************************************************************************/ -static my_bool show_handlerton(THD *thd, plugin_ref plugin, - void *arg) -{ - handlerton *default_type= (handlerton *) arg; - Protocol *protocol= thd->protocol; - handlerton *hton= plugin_data(plugin, handlerton *); - - if (!(hton->flags & HTON_HIDDEN)) - { - protocol->prepare_for_resend(); - protocol->store(plugin_name(plugin)->str, plugin_name(plugin)->length, - system_charset_info); - const char *option_name= show_comp_option_name[(int) hton->state]; - - if (hton->state == SHOW_OPTION_YES && default_type == hton) - option_name= "DEFAULT"; - protocol->store(option_name, system_charset_info); - protocol->store(plugin_decl(plugin)->descr, system_charset_info); - protocol->store(hton->commit ? "YES" : "NO", system_charset_info); - protocol->store(hton->prepare ? "YES" : "NO", system_charset_info); - protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info); - - return protocol->write() ? 1 : 0; - } - return 0; -} - -bool mysqld_show_storage_engines(THD *thd) -{ - List<Item> field_list; - Protocol *protocol= thd->protocol; - DBUG_ENTER("mysqld_show_storage_engines"); - - field_list.push_back(new Item_empty_string("Engine",10)); - field_list.push_back(new Item_empty_string("Support",10)); - field_list.push_back(new Item_empty_string("Comment",80)); - field_list.push_back(new Item_empty_string("Transactions",3)); - field_list.push_back(new Item_empty_string("XA",3)); - field_list.push_back(new Item_empty_string("Savepoints",3)); - - if (protocol->send_fields(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - DBUG_RETURN(TRUE); - - if (plugin_foreach(thd, show_handlerton, - MYSQL_STORAGE_ENGINE_PLUGIN, ha_default_handlerton(thd))) - DBUG_RETURN(TRUE); - - send_eof(thd); - DBUG_RETURN(FALSE); -} - static int make_version_string(char *buf, int buf_length, uint version) { return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); @@ -706,7 +654,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, else db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) | sctx->master_access); - if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname)) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->host_or_ip, dbname); @@ -831,7 +779,7 @@ mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd) } else { - if (my_write(fd, (const byte*) packet->ptr(), packet->length(), + if (my_write(fd, (const uchar*) packet->ptr(), packet->length(), MYF(MY_WME))) DBUG_RETURN(-1); } @@ -1660,7 +1608,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && thd->security_ctx->host_or_ip[0]) { - if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1))) + if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1))) my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); } @@ -1912,8 +1860,8 @@ int add_status_vars(SHOW_VAR *list) goto err; } while (list->name) - res|= insert_dynamic(&all_status_vars, (gptr)list++); - res|= insert_dynamic(&all_status_vars, (gptr)list); // appending NULL-element + res|= insert_dynamic(&all_status_vars, (uchar*)list++); + res|= insert_dynamic(&all_status_vars, (uchar*)list); // appending NULL-element all_status_vars.elements--; // but next insert_dynamic should overwite it if (status_vars_inited) sort_dynamic(&all_status_vars, show_var_cmp); @@ -2035,7 +1983,9 @@ static bool show_status_array(THD *thd, const char *wild, const char *prefix, TABLE *table, bool ucase_names) { - char buff[SHOW_VAR_FUNC_BUFF_SIZE], *prefix_end; + MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, long); + char * const buff= (char *) &buff_data; + char *prefix_end; /* the variable name should not be longer than 64 characters */ char name_buffer[64]; int len; @@ -2107,6 +2057,8 @@ static bool show_status_array(THD *thd, const char *wild, case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() end= int10_to_str(*(long*) value, buff, 10); break; + case SHOW_LONGLONG_STATUS: + value= ((char *) status_var + (ulonglong) value); case SHOW_LONGLONG: end= longlong10_to_str(*(longlong*) value, buff, 10); break; @@ -2649,7 +2601,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) &thd->col_access, 0, 1, with_i_schema) || sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(sctx->host, sctx->ip, sctx->priv_user, base_name,0) || - (grant_option && !check_grant_db(thd, base_name))) + !check_grant_db(thd, base_name)) #endif { List<char> files; @@ -2849,7 +2801,7 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(sctx->host, sctx->ip, sctx->priv_user, file_name,0) || - (grant_option && !check_grant_db(thd, file_name))) + !check_grant_db(thd, file_name)) #endif { load_db_opt_by_name(thd, file_name, &create); @@ -3098,7 +3050,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, for (ptr=show_table->field; (field= *ptr) ; ptr++) { const char *tmp_buff; - byte *pos; + uchar *pos; bool is_blob; uint flags=field->flags; char tmp[MAX_FIELD_WIDTH]; @@ -3176,7 +3128,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, table->field[5]->store("",0, cs); table->field[5]->set_notnull(); } - pos=(byte*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES"); + pos=(uchar*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES"); table->field[6]->store((const char*) pos, strlen((const char*) pos), cs); is_blob= (field->type() == MYSQL_TYPE_BLOB); @@ -3244,16 +3196,16 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, if (field->has_charset()) { - pos=(byte*) field->charset()->csname; + pos=(uchar*) field->charset()->csname; table->field[12]->store((const char*) pos, strlen((const char*) pos), cs); table->field[12]->set_notnull(); - pos=(byte*) field->charset()->name; + pos=(uchar*) field->charset()->name; table->field[13]->store((const char*) pos, strlen((const char*) pos), cs); table->field[13]->set_notnull(); } - pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : + pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); table->field[15]->store((const char*) pos, @@ -3311,6 +3263,7 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, handlerton *hton= plugin_data(plugin, handlerton *); const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; CHARSET_INFO *scs= system_charset_info; + handlerton *default_type= ha_default_handlerton(thd); DBUG_ENTER("iter_schema_engines"); if (!(hton->flags & HTON_HIDDEN)) @@ -3319,16 +3272,16 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, if (!(wild && wild[0] && wild_case_compare(scs, name->str,wild))) { - LEX_STRING state[2]= {{ C_STRING_WITH_LEN("ENABLED") }, - { C_STRING_WITH_LEN("DISABLED") }}; LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") }, { C_STRING_WITH_LEN("YES") }}; LEX_STRING *tmp; + const char *option_name= show_comp_option_name[(int) hton->state]; restore_record(table, s->default_values); table->field[0]->store(name->str, name->length, scs); - tmp= &state[test(hton->state)]; - table->field[1]->store(tmp->str, tmp->length, scs); + if (hton->state == SHOW_OPTION_YES && default_type == hton) + option_name= "DEFAULT"; + table->field[1]->store(option_name, strlen(option_name), scs); table->field[2]->store(plugin_decl(plugin)->descr, strlen(plugin_decl(plugin)->descr), scs); tmp= &yesno[test(hton->commit)]; @@ -3650,6 +3603,7 @@ static int get_schema_views_record(THD *thd, struct st_table_list *tables, DBUG_ENTER("get_schema_views_record"); char definer[USER_HOST_BUFF_SIZE]; uint definer_len; + bool updatable_view; if (tables->view) { @@ -3687,7 +3641,34 @@ static int get_schema_views_record(THD *thd, struct st_table_list *tables, else table->field[4]->store(STRING_WITH_LEN("NONE"), cs); - if (tables->updatable_view) + updatable_view= 0; + if (tables->algorithm != VIEW_ALGORITHM_TMPTABLE) + { + /* + We should use tables->view->select_lex.item_list here and + can not use Field_iterator_view because the view always uses + temporary algorithm during opening for I_S and + TABLE_LIST fields 'field_translation' & 'field_translation_end' + are uninitialized is this case. + */ + List<Item> *fields= &tables->view->select_lex.item_list; + List_iterator<Item> it(*fields); + Item *item; + Item_field *field; + /* + chech that at least one coulmn in view is updatable + */ + while ((item= it++)) + { + if ((field= item->filed_for_view_update()) && field->field && + !field->field->table->pos_in_table_list->schema_table) + { + updatable_view= 1; + break; + } + } + } + if (updatable_view) table->field[5]->store(STRING_WITH_LEN("YES"), cs); else table->field[5]->store(STRING_WITH_LEN("NO"), cs); @@ -3974,6 +3955,7 @@ static int get_schema_key_column_usage_record(THD *thd, } +#ifdef WITH_PARTITION_STORAGE_ENGINE static void collect_partition_expr(List<char> &field_list, String *str) { List_iterator<char> part_it(field_list); @@ -3988,6 +3970,7 @@ static void collect_partition_expr(List<char> &field_list, String *str) } return; } +#endif static void store_schema_partitions_record(THD *thd, TABLE *schema_table, @@ -4042,7 +4025,7 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table, table->field[22]->store(part_elem->part_comment, strlen(part_elem->part_comment), cs); else - table->field[22]->store(STRING_WITH_LEN("default"), cs); + table->field[22]->store(STRING_WITH_LEN(""), cs); if (part_elem->nodegroup_id != UNDEF_NODEGROUP) table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE); else @@ -5852,7 +5835,7 @@ int initialize_schema_table(st_plugin_int *plugin) DBUG_RETURN(0); err: - my_free((gptr)schema_table, MYF(0)); + my_free(schema_table, MYF(0)); DBUG_RETURN(1); } @@ -5869,8 +5852,7 @@ int finalize_schema_table(st_plugin_int *plugin) DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", plugin->name.str)); } - my_free((gptr)schema_table, MYF(0)); + my_free(schema_table, MYF(0)); } - DBUG_RETURN(0); } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 52af2f2dd90..6c7dea6bf22 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -32,7 +32,7 @@ required by the string function */ -extern gptr sql_alloc(unsigned size); +extern uchar* sql_alloc(unsigned size); extern void sql_element_free(void *ptr); #include "sql_string.h" @@ -496,7 +496,7 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) return TRUE; - if (my_fread(file, (byte*) Ptr + str_length, arg_length, my_flags)) + if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags)) { shrink(str_length); return TRUE; @@ -510,7 +510,7 @@ bool String::append(IO_CACHE* file, uint32 arg_length) { if (realloc(str_length+arg_length)) return TRUE; - if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + if (my_b_read(file, (uchar*) Ptr + str_length, arg_length)) { shrink(str_length); return TRUE; @@ -635,7 +635,7 @@ bool String::replace(uint32 offset,uint32 arg_length, { if (realloc(str_length+(uint32) diff)) return TRUE; - bmove_upp(Ptr+str_length+diff,Ptr+str_length, + bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length, str_length-offset-arg_length); } if (to_length) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 60d5286674b..047c210d6a5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -34,23 +34,25 @@ const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, - List<create_field> &create, bool ignore, + List<Create_field> &create, bool ignore, uint order_num, ORDER *order, ha_rows *copied,ha_rows *deleted, - enum enum_enable_or_disable keys_onoff); + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty); -static bool prepare_blob_field(THD *thd, create_field *sql_field); +static bool prepare_blob_field(THD *thd, Create_field *sql_field); static bool check_engine(THD *, const char *, HA_CREATE_INFO *); -static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, - List<create_field> *fields, - List<Key> *keys, bool tmp_table, - uint *db_options, - handler *file, KEY **key_info_buffer, - uint *key_count, int select_field_count); - -#define MYSQL50_TABLE_NAME_PREFIX "#mysql50#" -#define MYSQL50_TABLE_NAME_PREFIX_LENGTH 9 - +static bool +mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, + Alter_info *alter_info, + bool tmp_table, + uint *db_options, + handler *file, KEY **key_info_buffer, + uint *key_count, int select_field_count); +static bool +mysql_prepare_alter_table(THD *thd, TABLE *table, + HA_CREATE_INFO *create_info, + Alter_info *alter_info); /* Translate a file name to a table name (WL #1324). @@ -227,112 +229,6 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) } /* - Return values for compare_tables(). - If you make compare_tables() non-static, move them to a header file. -*/ -#define ALTER_TABLE_DATA_CHANGED 1 -#define ALTER_TABLE_INDEX_CHANGED 2 - - -/* - SYNOPSIS - mysql_copy_create_list() - orig_create_list Original list of created fields - inout::new_create_list Copy of original list - - RETURN VALUES - FALSE Success - TRUE Memory allocation error - - DESCRIPTION - mysql_prepare_table destroys the create_list and in some cases we need - this lists for more purposes. Thus we copy it specifically for use - by mysql_prepare_table -*/ - -static int mysql_copy_create_list(List<create_field> *orig_create_list, - List<create_field> *new_create_list) -{ - List_iterator<create_field> prep_field_it(*orig_create_list); - create_field *prep_field; - DBUG_ENTER("mysql_copy_create_list"); - - while ((prep_field= prep_field_it++)) - { - create_field *field= new create_field(*prep_field); - if (!field || new_create_list->push_back(field)) - { - mem_alloc_error(2); - DBUG_RETURN(TRUE); - } - } - DBUG_RETURN(FALSE); -} - - -/* - SYNOPSIS - mysql_copy_key_list() - orig_key Original list of keys - inout::new_key Copy of original list - - RETURN VALUES - FALSE Success - TRUE Memory allocation error - - DESCRIPTION - mysql_prepare_table destroys the key list and in some cases we need - this lists for more purposes. Thus we copy it specifically for use - by mysql_prepare_table -*/ - -static int mysql_copy_key_list(List<Key> *orig_key, - List<Key> *new_key) -{ - List_iterator<Key> prep_key_it(*orig_key); - Key *prep_key; - DBUG_ENTER("mysql_copy_key_list"); - - while ((prep_key= prep_key_it++)) - { - List<key_part_spec> prep_columns; - List_iterator<key_part_spec> prep_col_it(prep_key->columns); - key_part_spec *prep_col; - Key *temp_key; - - while ((prep_col= prep_col_it++)) - { - key_part_spec *prep_key_part; - - if (!(prep_key_part= new key_part_spec(*prep_col))) - { - mem_alloc_error(sizeof(key_part_spec)); - DBUG_RETURN(TRUE); - } - if (prep_columns.push_back(prep_key_part)) - { - mem_alloc_error(2); - DBUG_RETURN(TRUE); - } - } - if (!(temp_key= new Key(prep_key->type, prep_key->name, - &prep_key->key_create_info, - prep_key->generated, - prep_columns))) - { - mem_alloc_error(sizeof(Key)); - DBUG_RETURN(TRUE); - } - if (new_key->push_back(temp_key)) - { - mem_alloc_error(2); - DBUG_RETURN(TRUE); - } - } - DBUG_RETURN(FALSE); -} - -/* -------------------------------------------------------------------------- MODULE: DDL log @@ -408,11 +304,11 @@ static bool read_ddl_log_file_entry(uint entry_no) { bool error= FALSE; File file_id= global_ddl_log.file_id; - char *file_entry_buf= (char*)global_ddl_log.file_entry_buf; + uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf; uint io_size= global_ddl_log.io_size; DBUG_ENTER("read_ddl_log_file_entry"); - if (my_pread(file_id, (byte*)file_entry_buf, io_size, io_size * entry_no, + if (my_pread(file_id, file_entry_buf, io_size, io_size * entry_no, MYF(MY_WME)) != io_size) error= TRUE; DBUG_RETURN(error); @@ -436,7 +332,7 @@ static bool write_ddl_log_file_entry(uint entry_no) char *file_entry_buf= (char*)global_ddl_log.file_entry_buf; DBUG_ENTER("write_ddl_log_file_entry"); - if (my_pwrite(file_id, (byte*)file_entry_buf, + if (my_pwrite(file_id, (uchar*)file_entry_buf, IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE) error= TRUE; DBUG_RETURN(error); @@ -649,7 +545,9 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) int error= TRUE; char to_path[FN_REFLEN]; char from_path[FN_REFLEN]; +#ifdef WITH_PARTITION_STORAGE_ENGINE char *par_ext= (char*)".par"; +#endif handlerton *hton; DBUG_ENTER("execute_ddl_log_action"); @@ -1232,13 +1130,13 @@ void release_ddl_log() while (used_list) { DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry; - my_free((char*)used_list, MYF(0)); + my_free(used_list, MYF(0)); used_list= tmp; } while (free_list) { DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry; - my_free((char*)free_list, MYF(0)); + my_free(free_list, MYF(0)); free_list= tmp; } close_ddl_log(); @@ -1259,6 +1157,31 @@ void release_ddl_log() */ +/** + @brief construct a temporary shadow file name. + + @details Make a shadow file name used by ALTER TABLE to construct the + modified table (with keeping the original). The modified table is then + moved back as original table. The name must start with the temp file + prefix so it gets filtered out by table files listing routines. + + @param[out] buff buffer to receive the constructed name + @param bufflen size of buff + @param lpt alter table data structure + + @retval path length +*/ + +uint build_table_shadow_filename(char *buff, size_t bufflen, + ALTER_PARTITION_PARAM_TYPE *lpt) +{ + char tmp_name[FN_REFLEN]; + my_snprintf (tmp_name, sizeof (tmp_name), "%s-%s", tmp_file_prefix, + lpt->table_name); + return build_table_filename(buff, bufflen, lpt->db, tmp_name, "", FN_IS_TMP); +} + + /* SYNOPSIS mysql_write_frm() @@ -1299,24 +1222,18 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) /* Build shadow frm file name */ - build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#", 0); + build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt); strxmov(shadow_frm_name, shadow_path, reg_ext, NullS); if (flags & WFRM_WRITE_SHADOW) { - if (mysql_copy_create_list(lpt->create_list, - &lpt->new_create_list) || - mysql_copy_key_list(lpt->key_list, - &lpt->new_key_list) || - mysql_prepare_table(lpt->thd, lpt->create_info, - &lpt->new_create_list, - &lpt->new_key_list, - /*tmp_table*/ 1, - &lpt->db_options, - lpt->table->file, - &lpt->key_info_buffer, - &lpt->key_count, - /*select_field_count*/ 0)) + if (mysql_prepare_create_table(lpt->thd, lpt->create_info, + lpt->alter_info, + /*tmp_table*/ 1, + &lpt->db_options, + lpt->table->file, + &lpt->key_info_buffer, + &lpt->key_count, + /*select_field_count*/ 0)) { DBUG_RETURN(TRUE); } @@ -1328,6 +1245,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) if (part_info) { + TABLE_SHARE *share= lpt->table->s; if (!(part_syntax_buf= generate_partition_syntax(part_info, &syntax_len, TRUE, TRUE))) @@ -1335,7 +1253,16 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) DBUG_RETURN(TRUE); } part_info->part_info_string= part_syntax_buf; - part_info->part_info_len= syntax_len; + share->partition_info_len= part_info->part_info_len= syntax_len; + if (share->partition_info_buffer_size < syntax_len + 1) + { + share->partition_info_buffer_size= syntax_len+1; + if (!(share->partition_info= + (char*) alloc_root(&share->mem_root, syntax_len+1))) + DBUG_RETURN(TRUE); + + } + memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1); } } #endif @@ -1343,7 +1270,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) lpt->create_info->table_options= lpt->db_options; if ((mysql_create_frm(lpt->thd, shadow_frm_name, lpt->db, lpt->table_name, lpt->create_info, - lpt->new_create_list, lpt->key_count, + lpt->alter_info->create_list, lpt->key_count, lpt->key_info_buffer, lpt->table->file)) || lpt->table->file->create_handler_files(shadow_path, NULL, CHF_CREATE_FLAG, @@ -1362,13 +1289,13 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) handlers that have the main version of the frm file stored in the handler. */ - const void *data= 0; - uint length= 0; + uchar *data; + size_t length; if (readfrm(shadow_path, &data, &length) || packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len)) { - my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*)lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR)); + my_free(data, MYF(MY_ALLOW_ZERO_PTR)); + my_free(lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR)); mem_alloc_error(length); error= 1; goto end; @@ -2012,7 +1939,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, table_flags table flags DESCRIPTION - This function prepares a create_field instance. + This function prepares a Create_field instance. Fields such as pack_flag are valid after this call. RETURN VALUES @@ -2020,7 +1947,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, 1 Error */ -int prepare_create_field(create_field *sql_field, +int prepare_create_field(Create_field *sql_field, uint *blob_columns, int *timestamps, int *timestamps_with_niladic, longlong table_flags) @@ -2029,7 +1956,7 @@ int prepare_create_field(create_field *sql_field, DBUG_ENTER("prepare_field"); /* - This code came from mysql_prepare_table. + This code came from mysql_prepare_create_table. Indent preserved to make patching easier */ DBUG_ASSERT(sql_field->charset); @@ -2130,7 +2057,8 @@ int prepare_create_field(create_field *sql_field, break; case MYSQL_TYPE_BIT: /* - We have sql_field->pack_flag already set here, see mysql_prepare_table(). + We have sql_field->pack_flag already set here, see + mysql_prepare_create_table(). */ break; case MYSQL_TYPE_NEWDECIMAL: @@ -2179,11 +2107,10 @@ int prepare_create_field(create_field *sql_field, Preparation for table creation SYNOPSIS - mysql_prepare_table() + mysql_prepare_create_table() thd Thread object. create_info Create information (like MAX_ROWS). - fields List of fields to create. - keys List of keys to create. + alter_info List of columns and indexes to create tmp_table If a temporary table is to be created. db_options INOUT Table options (like HA_OPTION_PACK_RECORD). file The handler for the new table. @@ -2198,19 +2125,20 @@ int prepare_create_field(create_field *sql_field, sets create_info->varchar if the table has a varchar RETURN VALUES - 0 ok - -1 error + FALSE OK + TRUE error */ -static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, - List<create_field> *fields, - List<Key> *keys, bool tmp_table, - uint *db_options, - handler *file, KEY **key_info_buffer, - uint *key_count, int select_field_count) +static bool +mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, + Alter_info *alter_info, + bool tmp_table, + uint *db_options, + handler *file, KEY **key_info_buffer, + uint *key_count, int select_field_count) { const char *key_name; - create_field *sql_field,*dup_field; + Create_field *sql_field,*dup_field; uint field,null_fields,blob_columns,max_key_length; ulong record_offset= 0; KEY *key_info; @@ -2218,11 +2146,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, int timestamps= 0, timestamps_with_niladic= 0; int field_no,dup_no; int select_field_pos,auto_increment=0; - List_iterator<create_field> it(*fields),it2(*fields); + List_iterator<Create_field> it(alter_info->create_list); + List_iterator<Create_field> it2(alter_info->create_list); uint total_uneven_bit_length= 0; - DBUG_ENTER("mysql_prepare_table"); + DBUG_ENTER("mysql_prepare_create_table"); - select_field_pos= fields->elements - select_field_count; + select_field_pos= alter_info->create_list.elements - select_field_count; null_fields=blob_columns=0; create_info->varchar= 0; max_key_length= file->max_key_length(); @@ -2257,7 +2186,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), STRING_WITH_LEN("_bin")); my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* @@ -2271,26 +2200,23 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->sql_type == MYSQL_TYPE_SET || sql_field->sql_type == MYSQL_TYPE_ENUM)) { - Query_arena backup_arena; - bool need_to_change_arena= !thd->stmt_arena->is_conventional(); - if (need_to_change_arena) - { - /* Asser that we don't do that at every PS execute */ - DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || - thd->stmt_arena->is_first_sp_execute()); - thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); - } - + /* + Starting from 5.1 we work here with a copy of Create_field + created by the caller, not with the instance that was + originally created during parsing. It's OK to create + a temporary item and initialize with it a member of the + copy -- this item will be thrown away along with the copy + at the end of execution, and thus not introduce a dangling + pointer in the parsed tree of a prepared statement or a + stored procedure statement. + */ sql_field->def= sql_field->def->safe_charset_converter(save_cs); - if (need_to_change_arena) - thd->restore_active_arena(thd->stmt_arena, &backup_arena); - if (sql_field->def == NULL) { /* Could not convert */ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } @@ -2309,12 +2235,11 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!interval) { /* - Create the typelib in prepared statement memory if we're - executing one. + Create the typelib in runtime memory - we will free the + occupied memory at the same time when we free this + sql_field -- at the end of execution. */ - MEM_ROOT *stmt_root= thd->stmt_arena->mem_root; - - interval= sql_field->interval= typelib(stmt_root, + interval= sql_field->interval= typelib(thd->mem_root, sql_field->interval_list); List_iterator<String> int_it(sql_field->interval_list); String conv, *tmp; @@ -2331,7 +2256,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { uint cnv_errs; conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); - interval->type_names[i]= strmake_root(stmt_root, conv.ptr(), + interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(), conv.length()); interval->type_lengths[i]= conv.length(); } @@ -2348,7 +2273,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, comma_buf, comma_length, NULL, 0)) { my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr()); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } } @@ -2369,7 +2294,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if ((sql_field->flags & NOT_NULL_FLAG) != 0) { my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* else, NULL is an allowed value */ @@ -2385,7 +2310,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (not_found) { my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } calculate_interval_lengths(cs, interval, &dummy, &field_length); @@ -2403,7 +2328,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if ((sql_field->flags & NOT_NULL_FLAG) != 0) { my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* else, the defaults yield the correct length for NULLs. */ @@ -2414,7 +2339,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */ { my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } } @@ -2435,7 +2360,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->create_length_to_internal_length(); if (prepare_blob_field(thd, sql_field)) - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields++; @@ -2443,7 +2368,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (check_column_name(sql_field->field_name)) { my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* Check if we have used the same field name before */ @@ -2460,7 +2385,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (field_no < select_field_pos || dup_no >= select_field_pos) { my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } else { @@ -2511,9 +2436,9 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (prepare_create_field(sql_field, &blob_columns, ×tamps, ×tamps_with_niladic, file->ha_table_flags())) - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) - create_info->varchar= 1; + create_info->varchar= TRUE; sql_field->offset= record_offset; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) auto_increment++; @@ -2523,31 +2448,32 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS, ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (auto_increment > 1) { my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (auto_increment && (file->ha_table_flags() & HA_NO_AUTO_INCREMENT)) { my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS)) { my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* Create keys */ - List_iterator<Key> key_iterator(*keys), key_iterator2(*keys); + List_iterator<Key> key_iterator(alter_info->key_list); + List_iterator<Key> key_iterator2(alter_info->key_list); uint key_parts=0, fk_key_count=0; bool primary_key=0,unique_key=0; Key *key, *key2; @@ -2566,14 +2492,14 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (key->type == Key::FOREIGN_KEY) { fk_key_count++; - foreign_key *fk_key= (foreign_key*) key; + Foreign_key *fk_key= (Foreign_key*) key; if (fk_key->ref_columns.elements && fk_key->ref_columns.elements != fk_key->columns.elements) { my_error(ER_WRONG_FK_DEF, MYF(0), (fk_key->name ? fk_key->name : "foreign key without name"), ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } continue; } @@ -2582,7 +2508,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (key->columns.elements > tmp) { my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } key_name_str.str= (char*) key->name; key_name_str.length= key->name ? strlen(key->name) : 0; @@ -2590,7 +2516,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, system_charset_info, 1)) { my_error(ER_TOO_LONG_IDENT, MYF(0), key->name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } key_iterator2.rewind (); if (key->type != Key::FOREIGN_KEY) @@ -2630,27 +2556,27 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, !my_strcasecmp(system_charset_info,key->name,primary_key_name)) { my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } tmp=file->max_keys(); if (*key_count > tmp) { my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count)); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!*key_info_buffer || ! key_part_info) - DBUG_RETURN(-1); // Out of memory + DBUG_RETURN(TRUE); // Out of memory key_iterator.rewind(); key_number=0; for (; (key=key_iterator++) ; key_number++) { uint key_length=0; - key_part_spec *column; + Key_part_spec *column; if (key->name == ignore_key) { @@ -2680,7 +2606,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); #endif case Key::FOREIGN_KEY: key_number--; // Skip this key @@ -2703,7 +2629,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } /* @@ -2721,12 +2647,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (key_info->key_parts != 1) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX"); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } else if (key_info->algorithm == HA_KEY_ALG_RTREE) @@ -2735,15 +2661,15 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if ((key_info->key_parts & 1) == 1) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX"); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* TODO: To be deleted */ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX"); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_rtree.name, sym_group_rtree.needed_define); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); #endif } @@ -2759,12 +2685,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (key_info->block_size) key_info->flags|= HA_USES_BLOCK_SIZE; - List_iterator<key_part_spec> cols(key->columns), cols2(key->columns); + List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns); CHARSET_INFO *ft_key_charset=0; // for FULLTEXT for (uint column_nr=0 ; (column=cols++) ; column_nr++) { uint length; - key_part_spec *dup_column; + Key_part_spec *dup_column; it.rewind(); field=0; @@ -2776,7 +2702,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!sql_field) { my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } while ((dup_column= cols2++) != column) { @@ -2786,7 +2712,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, my_printf_error(ER_DUP_FIELDNAME, ER(ER_DUP_FIELDNAME),MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } cols2.rewind(); @@ -2819,7 +2745,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (key->type == Key::SPATIAL && column->length) { my_error(ER_WRONG_SUB_KEY, MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (f_is_blob(sql_field->pack_flag) || @@ -2828,7 +2754,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS)) { my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type == Field::GEOM_POINT) @@ -2836,7 +2762,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!column->length) { my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } #ifdef HAVE_SPATIAL @@ -2867,13 +2793,13 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!(file->ha_table_flags() & HA_NULL_IN_KEY)) { my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (key->type == Key::SPATIAL) { my_message(ER_SPATIAL_CANT_HAVE_NULL, ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } } @@ -2909,7 +2835,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, else { my_error(ER_TOO_LONG_KEY,MYF(0),length); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } } @@ -2922,7 +2848,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, column->length != length))) { my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) length=column->length; @@ -2930,7 +2856,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, else if (length == 0) { my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (length > file->max_key_part_length() && key->type != Key::FULLTEXT) { @@ -2949,7 +2875,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, else { my_error(ER_TOO_LONG_KEY,MYF(0),length); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } } key_part_info->length=(uint16) length; @@ -2978,7 +2904,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } key_name=primary_key_name; primary_key=1; @@ -2989,7 +2915,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (check_if_keyname_exists(key_name, *key_info_buffer, key_info)) { my_error(ER_DUP_KEYNAME, MYF(0), key_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } key_info->name=(char*) key_name; } @@ -2997,7 +2923,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!key_info->name || check_column_name(key_info->name)) { my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (!(key_info->flags & HA_NULL_PART_KEY)) unique_key=1; @@ -3005,7 +2931,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (key_length > max_key_length && key->type != Key::FULLTEXT) { my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } key_info++; } @@ -3013,19 +2939,19 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY)) { my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } if (auto_increment > 0) { my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* Sort keys in optimized order */ - qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY), + qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY), (qsort_cmp) sort_keys); create_info->null_bits= null_fields; - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3074,7 +3000,7 @@ static void set_table_default_charset(THD *thd, In this case the error is given */ -static bool prepare_blob_field(THD *thd, create_field *sql_field) +static bool prepare_blob_field(THD *thd, Create_field *sql_field) { DBUG_ENTER("prepare_blob_field"); @@ -3115,8 +3041,9 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field) /* - Preparation of create_field for SP function return values. - Based on code used in the inner loop of mysql_prepare_table() above + Preparation of Create_field for SP function return values. + Based on code used in the inner loop of mysql_prepare_create_table() + above. SYNOPSIS sp_prepare_create_field() @@ -3128,7 +3055,7 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field) */ -void sp_prepare_create_field(THD *thd, create_field *sql_field) +void sp_prepare_create_field(THD *thd, Create_field *sql_field) { if (sql_field->sql_type == MYSQL_TYPE_SET || sql_field->sql_type == MYSQL_TYPE_ENUM) @@ -3165,31 +3092,6 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field) /* - Copy HA_CREATE_INFO struct - SYNOPSIS - copy_create_info() - lex_create_info The create_info struct setup by parser - RETURN VALUES - > 0 A pointer to a copy of the lex_create_info - 0 Memory allocation error - DESCRIPTION - Allocate memory for copy of HA_CREATE_INFO structure from parser - to ensure we can reuse the parser struct in stored procedures - and prepared statements. -*/ - -static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info) -{ - HA_CREATE_INFO *create_info; - if (!(create_info= (HA_CREATE_INFO*)sql_alloc(sizeof(HA_CREATE_INFO)))) - mem_alloc_error(sizeof(HA_CREATE_INFO)); - else - memcpy((void*)create_info, (void*)lex_create_info, sizeof(HA_CREATE_INFO)); - return create_info; -} - - -/* Create a table SYNOPSIS @@ -3197,15 +3099,12 @@ static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info) thd Thread object db Database table_name Table name - lex_create_info Create information (like MAX_ROWS) + create_info Create information (like MAX_ROWS) fields List of fields to create keys List of keys to create internal_tmp_table Set to 1 if this is an internal temporary table (From ALTER TABLE) - select_field_count - use_copy_create_info Should we make a copy of create info (we do this - when this is called from sql_parse.cc where we - want to ensure lex object isn't manipulated. + select_field_count DESCRIPTION If one creates a temporary table, this is automatically opened @@ -3227,36 +3126,25 @@ static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info) bool mysql_create_table_no_lock(THD *thd, const char *db, const char *table_name, - HA_CREATE_INFO *lex_create_info, - List<create_field> &fields, - List<Key> &keys,bool internal_tmp_table, - uint select_field_count, - bool use_copy_create_info) + HA_CREATE_INFO *create_info, + Alter_info *alter_info, + bool internal_tmp_table, + uint select_field_count) { char path[FN_REFLEN]; uint path_length; const char *alias; uint db_options, key_count; KEY *key_info_buffer; - HA_CREATE_INFO *create_info; handler *file; bool error= TRUE; DBUG_ENTER("mysql_create_table_no_lock"); DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d", db, table_name, internal_tmp_table)); - if (use_copy_create_info) - { - if (!(create_info= copy_create_info(lex_create_info))) - { - DBUG_RETURN(TRUE); - } - } - else - create_info= lex_create_info; - + /* Check for duplicate fields and check type of table to create */ - if (!fields.elements) + if (!alter_info->create_list.elements) { my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS), MYF(0)); @@ -3308,7 +3196,7 @@ bool mysql_create_table_no_lock(THD *thd, Check that we don't use foreign keys in the table since it won't work even with InnoDB beneath it. */ - List_iterator<Key> key_iterator(keys); + List_iterator<Key> key_iterator(alter_info->key_list); Key *key; handlerton *part_engine_type= create_info->db_type; char *part_syntax_buf; @@ -3435,10 +3323,11 @@ bool mysql_create_table_no_lock(THD *thd, set_table_default_charset(thd, create_info, (char*) db); - if (mysql_prepare_table(thd, create_info, &fields, - &keys, internal_tmp_table, &db_options, file, - &key_info_buffer, &key_count, - select_field_count)) + if (mysql_prepare_create_table(thd, create_info, alter_info, + internal_tmp_table, + &db_options, file, + &key_info_buffer, &key_count, + select_field_count)) goto err; /* Check if table exists */ @@ -3546,7 +3435,8 @@ bool mysql_create_table_no_lock(THD *thd, create_info->table_options=db_options; path[path_length - reg_ext_length]= '\0'; // Remove .frm extension - if (rea_create_table(thd, path, db, table_name, create_info, fields, + if (rea_create_table(thd, path, db, table_name, + create_info, alter_info->create_list, key_count, key_info_buffer, file)) goto unlock_and_end; @@ -3598,10 +3488,9 @@ warn: bool mysql_create_table(THD *thd, const char *db, const char *table_name, HA_CREATE_INFO *create_info, - List<create_field> &fields, - List<Key> &keys,bool internal_tmp_table, - uint select_field_count, - bool use_copy_create_info) + Alter_info *alter_info, + bool internal_tmp_table, + uint select_field_count) { TABLE *name_lock= 0; bool result; @@ -3610,7 +3499,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, /* Wait for any database locks */ pthread_mutex_lock(&LOCK_lock_db); while (!thd->killed && - hash_search(&lock_db_cache,(byte*) db, strlen(db))) + hash_search(&lock_db_cache,(uchar*) db, strlen(db))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); pthread_mutex_lock(&LOCK_lock_db); @@ -3651,9 +3540,9 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, } result= mysql_create_table_no_lock(thd, db, table_name, create_info, - fields, keys, internal_tmp_table, - select_field_count, - use_copy_create_info); + alter_info, + internal_tmp_table, + select_field_count); unlock: if (name_lock) @@ -4153,7 +4042,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, table->next_global= 0; save_next_local= table->next_local; table->next_local= 0; - select->table_list.first= (byte*)table; + select->table_list.first= (uchar*)table; /* Time zone tables and SP tables can be add to lex->query_tables list, so it have to be prepared. @@ -4213,34 +4102,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, */ if (!table->table) { - char buf[ERRMSGSIZE+ERRMSGSIZE+2]; - const char *err_msg; - protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); - protocol->store(operator_name, system_charset_info); - protocol->store(STRING_WITH_LEN("error"), system_charset_info); - if (!(err_msg=thd->net.last_error)) - err_msg=ER(ER_CHECK_NO_SUCH_TABLE); + if (!thd->warn_list.elements) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE)); /* if it was a view will check md5 sum */ if (table->view && view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM) - { - strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS); - err_msg= (const char *)buf; - } - protocol->store(err_msg, system_charset_info); - lex->cleanup_after_one_table_open(); - thd->clear_error(); - /* - View opening can be interrupted in the middle of process so some - tables can be left opening - */ - ha_autocommit_or_rollback(thd, 1); - close_thread_tables(thd); - lex->reset_query_tables_list(FALSE); - if (protocol->write()) - goto err; - continue; + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM)); + result_code= HA_ADMIN_CORRUPT; + goto send_result; } if (table->view) @@ -4307,10 +4178,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, (table->table->file->ha_check_for_upgrade(check_opt) == HA_ADMIN_NEEDS_ALTER)) { + my_bool save_no_send_ok= thd->net.no_send_ok; ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); tmp_disable_binlog(thd); // binlogging is done by caller if wanted - result_code= mysql_recreate_table(thd, table, 0); + thd->net.no_send_ok= TRUE; + result_code= mysql_recreate_table(thd, table); + thd->net.no_send_ok= save_no_send_ok; reenable_binlog(thd); goto send_result; } @@ -4323,6 +4197,23 @@ send_result: lex->cleanup_after_one_table_open(); thd->clear_error(); // these errors shouldn't get client + { + List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); + MYSQL_ERROR *err; + while ((err= it++)) + { + protocol->prepare_for_resend(); + protocol->store(table_name, system_charset_info); + protocol->store((char*) operator_name, system_charset_info); + protocol->store(warning_level_names[err->level].str, + warning_level_names[err->level].length, + system_charset_info); + protocol->store(err->msg, system_charset_info); + if (protocol->write()) + goto err; + } + mysql_reset_errors(thd, true); + } protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); protocol->store(operator_name, system_charset_info); @@ -4389,6 +4280,7 @@ send_result_message: case HA_ADMIN_TRY_ALTER: { + my_bool save_no_send_ok= thd->net.no_send_ok; /* This is currently used only by InnoDB. ha_innobase::optimize() answers "try with alter", so here we close the table, do an ALTER TABLE, @@ -4400,7 +4292,9 @@ send_result_message: *save_next_global= table->next_global; table->next_local= table->next_global= 0; tmp_disable_binlog(thd); // binlogging is done by caller if wanted - result_code= mysql_recreate_table(thd, table, 0); + thd->net.no_send_ok= TRUE; + result_code= mysql_recreate_table(thd, table); + thd->net.no_send_ok= save_no_send_ok; reenable_binlog(thd); ha_autocommit_or_rollback(thd, 0); close_thread_tables(thd); @@ -4525,6 +4419,8 @@ send_result_message: bool mysql_backup_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_backup_table"); + WARN_DEPRECATED(thd, "5.2", "BACKUP TABLE", + "MySQL Administrator (mysqldump, mysql)"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, "backup", TL_READ, 0, 0, 0, 0, &handler::backup, 0)); @@ -4534,6 +4430,8 @@ bool mysql_backup_table(THD* thd, TABLE_LIST* table_list) bool mysql_restore_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_restore_table"); + WARN_DEPRECATED(thd, "5.2", "RESTORE TABLE", + "MySQL Administrator (mysqldump, mysql)"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, "restore", TL_WRITE, 1, 1, 0, &prepare_for_restore, @@ -4670,114 +4568,46 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) SYNOPSIS mysql_create_like_table() thd Thread object - table Table list (one table only) + table Table list element for target table + src_table Table list element for source table create_info Create info - table_ident Src table_ident RETURN VALUES FALSE OK TRUE error */ -bool mysql_create_like_table(THD* thd, TABLE_LIST* table, - HA_CREATE_INFO *lex_create_info, - Table_ident *table_ident) +bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, + HA_CREATE_INFO *create_info) { - TABLE *tmp_table, *name_lock= 0; + TABLE *name_lock= 0; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; - char src_table_name_buff[FN_REFLEN], src_db_name_buff[FN_REFLEN]; uint dst_path_length; char *db= table->db; char *table_name= table->table_name; - char *src_db; - char *src_table= table_ident->table.str; int err; bool res= TRUE; - enum legacy_db_type not_used; - HA_CREATE_INFO *create_info; + uint not_used; #ifdef WITH_PARTITION_STORAGE_ENGINE char tmp_path[FN_REFLEN]; #endif char ts_name[FN_LEN]; - TABLE_LIST src_tables_list; DBUG_ENTER("mysql_create_like_table"); - if (!(create_info= copy_create_info(lex_create_info))) - { - DBUG_RETURN(TRUE); - } - DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */ - src_db= table_ident->db.str; - /* - Validate the source table - */ - if (check_string_char_length(&table_ident->table, "", NAME_CHAR_LEN, - system_charset_info, 1) || - (table_ident->table.length && - check_table_name(src_table,table_ident->table.length))) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); - DBUG_RETURN(TRUE); - } - if (!src_db || check_db_name(&table_ident->db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); - DBUG_RETURN(-1); - } + /* CREATE TABLE ... LIKE is not allowed for views. */ + src_table->required_type= FRMTYPE_TABLE; - if ((tmp_table= find_temporary_table(thd, src_db, src_table))) - strxmov(src_path, tmp_table->s->path.str, reg_ext, NullS); - else - { - build_table_filename(src_path, sizeof(src_path), - src_db, src_table, reg_ext, 0); - /* Resolve symlinks (for windows) */ - unpack_filename(src_path, src_path); - if (lower_case_table_names) - my_casedn_str(files_charset_info, src_path); - if (access(src_path, F_OK)) - { - my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); - goto err; - } - } - - /* - create like should be not allowed for Views, Triggers, ... + /* + By opening source table we guarantee that it exists and no concurrent + DDL operation will mess with it. Later we also take an exclusive + name-lock on target table name, which makes copying of .frm file, + call to ha_create_table() and binlogging atomic against concurrent DML + and DDL operations on target table. Thus by holding both these "locks" + we ensure that our statement is properly isolated from all concurrent + operations which matter. */ - if (mysql_frm_type(thd, src_path, ¬_used) != FRMTYPE_TABLE) - { - my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE"); - goto err; - } - - if (lower_case_table_names) - { - if (src_db) - { - strmake(src_db_name_buff, src_db, - min(sizeof(src_db_name_buff) - 1, table_ident->db.length)); - my_casedn_str(files_charset_info, src_db_name_buff); - src_db= src_db_name_buff; - } - if (src_table) - { - strmake(src_table_name_buff, src_table, - min(sizeof(src_table_name_buff) - 1, table_ident->table.length)); - my_casedn_str(files_charset_info, src_table_name_buff); - src_table= src_table_name_buff; - } - } - - bzero((gptr)&src_tables_list, sizeof(src_tables_list)); - src_tables_list.db= src_db; - src_tables_list.db_length= table_ident->db.length; - src_tables_list.lock_type= TL_READ; - src_tables_list.table_name= src_table; - src_tables_list.alias= src_table; - - if (simple_open_n_lock_tables(thd, &src_tables_list)) + if (open_tables(thd, &src_table, ¬_used, 0)) DBUG_RETURN(TRUE); /* @@ -4786,17 +4616,19 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, Add something to get possible tablespace info from src table, it can get valid tablespace name only for disk-base ndb table */ - if ((src_tables_list.table->file->get_tablespace_name(thd, ts_name, FN_LEN))) + if ((src_table->table->file->get_tablespace_name(thd, ts_name, FN_LEN))) { create_info->tablespace= ts_name; create_info->storage_media= HA_SM_DISK; } - /* - Validate the destination table + strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS); - skip the destination table name checking as this is already - validated. + DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000);); + + /* + Check that destination tables does not exist. Note that its name + was already checked when it was added to the table list. */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { @@ -4817,15 +4649,29 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, goto table_exists; } + DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000);); + /* Create a new table by copying from source table + + Altough exclusive name-lock on target table protects us from concurrent + DML and DDL operations on it we still want to wrap .FRM creation and call + to ha_create_table() in critical section protected by LOCK_open in order + to provide minimal atomicity against operations which disregard name-locks, + like I_S implementation, for example. This is a temporary and should not + be copied. Instead we should fix our code to always honor name-locks. + + Also some engines (e.g. NDB cluster) require that LOCK_open should be held + during the call to ha_create_table(). See bug #28614 for more info. */ + VOID(pthread_mutex_lock(&LOCK_open)); if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) { if (my_errno == ENOENT) my_error(ER_BAD_DB_ERROR,MYF(0),db); else my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno); + VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -4847,10 +4693,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, strmov(src_path, tmp_path); my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)); #endif + + DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000);); + dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm - pthread_mutex_lock(&LOCK_open); err= ha_create_table(thd, dst_path, db, table_name, create_info, 1); - pthread_mutex_unlock(&LOCK_open); + VOID(pthread_mutex_unlock(&LOCK_open)); if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { if (err || !open_temporary_table(thd, dst_path, db, table_name, 1)) @@ -4867,6 +4715,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, goto err; /* purecov: inspected */ } + DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000);); + /* We have to write the query before we unlock the tables. */ @@ -4886,14 +4736,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, 3 temporary normal Nothing 4 temporary temporary Nothing ==== ========= ========= ============================== - - The variable 'tmp_table' below is used to see if the source - table is a temporary table: if it is set, then the source table - was a temporary table and we can take apropriate actions. */ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - if (tmp_table) // Case 2 + if (src_table->table->s->tmp_table) // Case 2 { char buf[2048]; String query(buf, sizeof(buf), system_charset_info); @@ -4975,7 +4821,7 @@ bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt) DBUG_ENTER("mysql_check_table"); DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, "check", lock_type, - 0, HA_OPEN_FOR_REPAIR, 0, 0, + 0, 0, HA_OPEN_FOR_REPAIR, 0, &handler::ha_check, &view_checksum)); } @@ -5053,12 +4899,18 @@ err: SYNOPSIS compare_tables() table The original table. - create_list The fields for the new table. - key_info_buffer An array of KEY structs for the new indexes. - key_count The number of elements in the array. + alter_info Alter options, fields and keys for the new + table. create_info Create options for the new table. - alter_info Alter options. order_num Number of order list elements. + need_copy_table OUT Result of the comparison. Undefined if error. + Otherwise is one of: + ALTER_TABLE_METADATA_ONLY No copy needed + ALTER_TABLE_DATA_CHANGED Data changes, + copy needed + ALTER_TABLE_INDEX_CHANGED Index changes, + copy might be needed + key_info_buffer OUT An array of KEY structs for new indexes index_drop_buffer OUT An array of offsets into table->key_info. index_drop_count OUT The number of elements in the array. index_add_buffer OUT An array of offsets into key_info_buffer. @@ -5080,27 +4932,69 @@ err: that need to be dropped and/or (re-)created. RETURN VALUES - 0 No copy needed - ALTER_TABLE_DATA_CHANGED Data changes, copy needed - ALTER_TABLE_INDEX_CHANGED Index changes, copy might be needed + TRUE error + FALSE success */ -static uint compare_tables(TABLE *table, List<create_field> *create_list, - KEY *key_info_buffer, uint key_count, - HA_CREATE_INFO *create_info, - ALTER_INFO *alter_info, uint order_num, - uint *index_drop_buffer, uint *index_drop_count, - uint *index_add_buffer, uint *index_add_count, - bool varchar) +static +bool +compare_tables(TABLE *table, + Alter_info *alter_info, + HA_CREATE_INFO *create_info, + uint order_num, + enum_alter_table_change_level *need_copy_table, + KEY **key_info_buffer, + uint **index_drop_buffer, uint *index_drop_count, + uint **index_add_buffer, uint *index_add_count) { Field **f_ptr, *field; uint changes= 0, tmp; - List_iterator_fast<create_field> new_field_it(*create_list); - create_field *new_field; + uint key_count; + List_iterator_fast<Create_field> new_field_it(alter_info->create_list); + Create_field *new_field; KEY_PART_INFO *key_part; KEY_PART_INFO *end; + /* + Remember if the new definition has new VARCHAR column; + create_info->varchar will be reset in mysql_prepare_create_table. + */ + bool varchar= create_info->varchar; DBUG_ENTER("compare_tables"); + { + THD *thd= table->in_use; + /* + Create a copy of alter_info. + To compare the new and old table definitions, we need to "prepare" + the new definition - transform it from parser output to a format + that describes the final table layout (all column defaults are + initialized, duplicate columns are removed). This is done by + mysql_prepare_create_table. Unfortunately, + mysql_prepare_create_table performs its transformations + "in-place", that is, modifies the argument. Since we would + like to keep compare_tables() idempotent (not altering any + of the arguments) we create a copy of alter_info here and + pass it to mysql_prepare_create_table, then use the result + to evaluate possibility of fast ALTER TABLE, and then + destroy the copy. + */ + Alter_info tmp_alter_info(*alter_info, thd->mem_root); + uint db_options= 0; /* not used */ + /* Create the prepared information. */ + if (mysql_prepare_create_table(thd, create_info, + &tmp_alter_info, + (table->s->tmp_table != NO_TMP_TABLE), + &db_options, + table->file, key_info_buffer, + &key_count, 0)) + DBUG_RETURN(1); + /* Allocate result buffers. */ + if (! (*index_drop_buffer= + (uint*) thd->alloc(sizeof(uint) * table->s->keys)) || + ! (*index_add_buffer= + (uint*) thd->alloc(sizeof(uint) * tmp_alter_info.key_list.elements))) + DBUG_RETURN(1); + } /* Some very basic checks. If number of fields changes, or the handler, we need to run full ALTER TABLE. In the future @@ -5127,7 +5021,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, prior to 5.0 branch. See BUG#6236. */ - if (table->s->fields != create_list->elements || + if (table->s->fields != alter_info->create_list.elements || table->s->db_type() != create_info->db_type || table->s->tmp_table || create_info->used_fields & HA_CREATE_USED_ENGINE || @@ -5137,7 +5031,10 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, order_num || !table->s->mysql_version || (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar)) - DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); + { + *need_copy_table= ALTER_TABLE_DATA_CHANGED; + DBUG_RETURN(0); + } /* Go through fields and check if the original ones are compatible @@ -5153,7 +5050,10 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, /* Check that NULL behavior is same for old and new fields */ if ((new_field->flags & NOT_NULL_FLAG) != (uint) (field->flags & NOT_NULL_FLAG)) - DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); + { + *need_copy_table= ALTER_TABLE_DATA_CHANGED; + DBUG_RETURN(0); + } /* Don't pack rows in old tables if the user has requested this. */ if (create_info->row_type == ROW_TYPE_DYNAMIC || @@ -5171,7 +5071,10 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, /* Evaluate changes bitmap and send to check_if_incompatible_data() */ if (!(tmp= field->is_equal(new_field))) - DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); + { + *need_copy_table= ALTER_TABLE_DATA_CHANGED; + DBUG_RETURN(0); + } // Clear indexed marker field->flags&= ~FIELD_IN_ADD_INDEX; changes|= tmp; @@ -5184,7 +5087,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, KEY *table_key; KEY *table_key_end= table->key_info + table->s->keys; KEY *new_key; - KEY *new_key_end= key_info_buffer + key_count; + KEY *new_key_end= *key_info_buffer + key_count; DBUG_PRINT("info", ("index count old: %d new: %d", table->s->keys, key_count)); @@ -5200,7 +5103,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, KEY_PART_INFO *new_part; /* Search a new key with the same name. */ - for (new_key= key_info_buffer; new_key < new_key_end; new_key++) + for (new_key= *key_info_buffer; new_key < new_key_end; new_key++) { if (! strcmp(table_key->name, new_key->name)) break; @@ -5208,7 +5111,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, if (new_key >= new_key_end) { /* Key not found. Add the offset of the key to the drop buffer. */ - index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info; + (*index_drop_buffer)[(*index_drop_count)++]= table_key - table->key_info; DBUG_PRINT("info", ("index dropped: '%s'", table_key->name)); continue; } @@ -5241,8 +5144,8 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, index_changed: /* Key modified. Add the offset of the key to both buffers. */ - index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info; - index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer; + (*index_drop_buffer)[(*index_drop_count)++]= table_key - table->key_info; + (*index_add_buffer)[(*index_add_count)++]= new_key - *key_info_buffer; key_part= new_key->key_part; end= key_part + new_key->key_parts; for(; key_part != end; key_part++) @@ -5258,7 +5161,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, /* Step through all keys of the new table and find matching old keys. */ - for (new_key= key_info_buffer; new_key < new_key_end; new_key++) + for (new_key= *key_info_buffer; new_key < new_key_end; new_key++) { /* Search an old key with the same name. */ for (table_key= table->key_info; table_key < table_key_end; table_key++) @@ -5269,7 +5172,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, if (table_key >= table_key_end) { /* Key not found. Add the offset of the key to the add buffer. */ - index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer; + (*index_add_buffer)[(*index_add_count)++]= new_key - *key_info_buffer; key_part= new_key->key_part; end= key_part + new_key->key_parts; for(; key_part != end; key_part++) @@ -5284,12 +5187,19 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, /* Check if changes are compatible with current handler without a copy */ if (table->file->check_if_incompatible_data(create_info, changes)) - DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); + { + *need_copy_table= ALTER_TABLE_DATA_CHANGED; + DBUG_RETURN(0); + } if (*index_drop_count || *index_add_count) - DBUG_RETURN(ALTER_TABLE_INDEX_CHANGED); + { + *need_copy_table= ALTER_TABLE_INDEX_CHANGED; + DBUG_RETURN(0); + } - DBUG_RETURN(0); // Tables are compatible + *need_copy_table= ALTER_TABLE_METADATA_ONLY; // Tables are compatible + DBUG_RETURN(0); } @@ -5341,6 +5251,409 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, } +/** + Prepare column and key definitions for CREATE TABLE in ALTER TABLE. + + This function transforms parse output of ALTER TABLE - lists of + columns and keys to add, drop or modify into, essentially, + CREATE TABLE definition - a list of columns and keys of the new + table. While doing so, it also performs some (bug not all) + semantic checks. + + This function is invoked when we know that we're going to + perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE + is not possible, perhaps because the ALTER statement contains + instructions that require change in table data, not only in + table definition or indexes. + + @param[in,out] thd thread handle. Used as a memory pool + and source of environment information. + @param[in] table the source table, open and locked + Used as an interface to the storage engine + to acquire additional information about + the original table. + @param[in,out] create_info A blob with CREATE/ALTER TABLE + parameters + @param[in,out] alter_info Another blob with ALTER/CREATE parameters. + Originally create_info was used only in + CREATE TABLE and alter_info only in ALTER TABLE. + But since ALTER might end-up doing CREATE, + this distinction is gone and we just carry + around two structures. + + @return + Fills various create_info members based on information retrieved + from the storage engine. + Sets create_info->varchar if the table has a VARCHAR column. + Prepares alter_info->create_list and alter_info->key_list with + columns and keys of the new table. + @retval TRUE error, out of memory or a semantical error in ALTER + TABLE instructions + @retval FALSE success +*/ + +static bool +mysql_prepare_alter_table(THD *thd, TABLE *table, + HA_CREATE_INFO *create_info, + Alter_info *alter_info) +{ + /* New column definitions are added here */ + List<Create_field> new_create_list; + /* New key definitions are added here */ + List<Key> new_key_list; + List_iterator<Alter_drop> drop_it(alter_info->drop_list); + List_iterator<Create_field> def_it(alter_info->create_list); + List_iterator<Alter_column> alter_it(alter_info->alter_list); + List_iterator<Key> key_it(alter_info->key_list); + List_iterator<Create_field> find_it(new_create_list); + List_iterator<Create_field> field_it(new_create_list); + List<Key_part_spec> key_parts; + uint db_create_options= (table->s->db_create_options + & ~(HA_OPTION_PACK_RECORD)); + uint used_fields= create_info->used_fields; + KEY *key_info=table->key_info; + bool rc= TRUE; + + DBUG_ENTER("mysql_prepare_alter_table"); + + create_info->varchar= FALSE; + /* Let new create options override the old ones */ + if (!(used_fields & HA_CREATE_USED_MIN_ROWS)) + create_info->min_rows= table->s->min_rows; + if (!(used_fields & HA_CREATE_USED_MAX_ROWS)) + create_info->max_rows= table->s->max_rows; + if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) + create_info->avg_row_length= table->s->avg_row_length; + if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) + create_info->default_table_charset= table->s->table_charset; + if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field) + { + /* Table has an autoincrement, copy value to new table */ + table->file->info(HA_STATUS_AUTO); + create_info->auto_increment_value= table->file->stats.auto_increment_value; + } + if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) + create_info->key_block_size= table->s->key_block_size; + + if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY) + { + char *tablespace= static_cast<char *>(thd->alloc(FN_LEN)); + /* + Regular alter table of disk stored table (no tablespace/storage change) + Copy tablespace name + */ + if (tablespace && + (table->file->get_tablespace_name(thd, tablespace, FN_LEN))) + create_info->tablespace= tablespace; + } + restore_record(table, s->default_values); // Empty record for DEFAULT + Create_field *def; + + /* + First collect all fields from table which isn't in drop_list + */ + Field **f_ptr,*field; + for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) + { + if (field->type() == MYSQL_TYPE_STRING) + create_info->varchar= TRUE; + /* Check if field should be dropped */ + Alter_drop *drop; + drop_it.rewind(); + while ((drop=drop_it++)) + { + if (drop->type == Alter_drop::COLUMN && + !my_strcasecmp(system_charset_info,field->field_name, drop->name)) + { + /* Reset auto_increment value if it was dropped */ + if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && + !(used_fields & HA_CREATE_USED_AUTO)) + { + create_info->auto_increment_value=0; + create_info->used_fields|=HA_CREATE_USED_AUTO; + } + break; + } + } + if (drop) + { + drop_it.remove(); + continue; + } + /* Check if field is changed */ + def_it.rewind(); + while ((def=def_it++)) + { + if (def->change && + !my_strcasecmp(system_charset_info,field->field_name, def->change)) + break; + } + if (def) + { // Field is changed + def->field=field; + if (!def->after) + { + new_create_list.push_back(def); + def_it.remove(); + } + } + else + { + /* + This field was not dropped and not changed, add it to the list + for the new table. + */ + def= new Create_field(field, field); + new_create_list.push_back(def); + alter_it.rewind(); // Change default if ALTER + Alter_column *alter; + while ((alter=alter_it++)) + { + if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) + break; + } + if (alter) + { + if (def->sql_type == MYSQL_TYPE_BLOB) + { + my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); + goto err; + } + if ((def->def=alter->def)) // Use new default + def->flags&= ~NO_DEFAULT_VALUE_FLAG; + else + def->flags|= NO_DEFAULT_VALUE_FLAG; + alter_it.remove(); + } + } + } + def_it.rewind(); + while ((def=def_it++)) // Add new columns + { + if (def->change && ! def->field) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name); + goto err; + } + /* + Check that the DATE/DATETIME not null field we are going to add is + either has a default value or the '0000-00-00' is allowed by the + set sql mode. + If the '0000-00-00' value isn't allowed then raise the error_if_not_empty + flag to allow ALTER TABLE only if the table to be altered is empty. + */ + if ((def->sql_type == MYSQL_TYPE_DATE || + def->sql_type == MYSQL_TYPE_NEWDATE || + def->sql_type == MYSQL_TYPE_DATETIME) && + !alter_info->datetime_field && + !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) && + thd->variables.sql_mode & MODE_NO_ZERO_DATE) + { + alter_info->datetime_field= def; + alter_info->error_if_not_empty= TRUE; + } + if (!def->after) + new_create_list.push_back(def); + else if (def->after == first_keyword) + new_create_list.push_front(def); + else + { + Create_field *find; + find_it.rewind(); + while ((find=find_it++)) // Add new columns + { + if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) + break; + } + if (!find) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name); + goto err; + } + find_it.after(def); // Put element after this + alter_info->change_level= ALTER_TABLE_DATA_CHANGED; + } + } + if (alter_info->alter_list.elements) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), + alter_info->alter_list.head()->name, table->s->table_name); + goto err; + } + if (!new_create_list.elements) + { + my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS), + MYF(0)); + goto err; + } + + /* + Collect all keys which isn't in drop list. Add only those + for which some fields exists. + */ + + for (uint i=0 ; i < table->s->keys ; i++,key_info++) + { + char *key_name= key_info->name; + Alter_drop *drop; + drop_it.rewind(); + while ((drop=drop_it++)) + { + if (drop->type == Alter_drop::KEY && + !my_strcasecmp(system_charset_info,key_name, drop->name)) + break; + } + if (drop) + { + drop_it.remove(); + continue; + } + + KEY_PART_INFO *key_part= key_info->key_part; + key_parts.empty(); + for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) + { + if (!key_part->field) + continue; // Wrong field (from UNIREG) + const char *key_part_name=key_part->field->field_name; + Create_field *cfield; + field_it.rewind(); + while ((cfield=field_it++)) + { + if (cfield->change) + { + if (!my_strcasecmp(system_charset_info, key_part_name, + cfield->change)) + break; + } + else if (!my_strcasecmp(system_charset_info, + key_part_name, cfield->field_name)) + break; + } + if (!cfield) + continue; // Field is removed + uint key_part_length=key_part->length; + if (cfield->field) // Not new field + { + /* + If the field can't have only a part used in a key according to its + new type, or should not be used partially according to its + previous type, or the field length is less than the key part + length, unset the key part length. + + We also unset the key part length if it is the same as the + old field's length, so the whole new field will be used. + + BLOBs may have cfield->length == 0, which is why we test it before + checking whether cfield->length < key_part_length (in chars). + */ + if (!Field::type_can_have_key_part(cfield->field->type()) || + !Field::type_can_have_key_part(cfield->sql_type) || + /* spatial keys can't have sub-key length */ + (key_info->flags & HA_SPATIAL) || + (cfield->field->field_length == key_part_length && + !f_is_blob(key_part->key_type)) || + (cfield->length && (cfield->length < key_part_length / + key_part->field->charset()->mbmaxlen))) + key_part_length= 0; // Use whole field + } + key_part_length /= key_part->field->charset()->mbmaxlen; + key_parts.push_back(new Key_part_spec(cfield->field_name, + key_part_length)); + } + if (key_parts.elements) + { + KEY_CREATE_INFO key_create_info; + Key *key; + enum Key::Keytype key_type; + bzero((char*) &key_create_info, sizeof(key_create_info)); + + key_create_info.algorithm= key_info->algorithm; + if (key_info->flags & HA_USES_BLOCK_SIZE) + key_create_info.block_size= key_info->block_size; + if (key_info->flags & HA_USES_PARSER) + key_create_info.parser_name= *key_info->parser_name; + + if (key_info->flags & HA_SPATIAL) + key_type= Key::SPATIAL; + else if (key_info->flags & HA_NOSAME) + { + if (! my_strcasecmp(system_charset_info, key_name, primary_key_name)) + key_type= Key::PRIMARY; + else + key_type= Key::UNIQUE; + } + else if (key_info->flags & HA_FULLTEXT) + key_type= Key::FULLTEXT; + else + key_type= Key::MULTIPLE; + + key= new Key(key_type, key_name, + &key_create_info, + test(key_info->flags & HA_GENERATED_KEY), + key_parts); + new_key_list.push_back(key); + } + } + { + Key *key; + while ((key=key_it++)) // Add new keys + { + if (key->type != Key::FOREIGN_KEY) + new_key_list.push_back(key); + if (key->name && + !my_strcasecmp(system_charset_info,key->name,primary_key_name)) + { + my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); + goto err; + } + } + } + + if (alter_info->drop_list.elements) + { + my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), + alter_info->drop_list.head()->name); + goto err; + } + if (alter_info->alter_list.elements) + { + my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), + alter_info->alter_list.head()->name); + goto err; + } + + if (!create_info->comment.str) + { + create_info->comment.str= table->s->comment.str; + create_info->comment.length= table->s->comment.length; + } + + table->file->update_create_info(create_info); + if ((create_info->table_options & + (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) || + (used_fields & HA_CREATE_USED_PACK_KEYS)) + db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); + if (create_info->table_options & + (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM)) + db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM); + if (create_info->table_options & + (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE)) + db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE | + HA_OPTION_NO_DELAY_KEY_WRITE); + create_info->table_options|= db_create_options; + + if (table->s->tmp_table) + create_info->options|=HA_LEX_CREATE_TMP_TABLE; + + rc= FALSE; + alter_info->create_list.swap(new_create_list); + alter_info->key_list.swap(new_key_list); +err: + DBUG_RETURN(rc); +} + + /* Alter table @@ -5349,21 +5662,14 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, thd Thread handle new_db If there is a RENAME clause new_name If there is a RENAME clause - lex_create_info Information from the parsing phase. Since some - clauses are common to CREATE and ALTER TABLE, the - data is stored in lex->create_info. The non-common - is stored in lex->alter_info. + create_info Information from the parsing phase about new + table properties. table_list The table to change. - fields lex->create_list - List of fields to be changed, - added or dropped. - keys lex->key_list - List of keys to be changed, added or - dropped. + alter_info Lists of fields, keys to be changed, added + or dropped. order_num How many ORDER BY fields has been specified. order List of fields to ORDER BY. ignore Whether we have ALTER IGNORE TABLE - alter_info Information from the parsing phase specific to ALTER - TABLE and not shared with CREATE TABLE. - do_send_ok Whether to call send_ok() on success. DESCRIPTION This is a veery long function and is everything but the kitchen sink :) @@ -5375,15 +5681,15 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, the table and/or enabling/disabling the keys. In this case, the FRM is not changed, directly by mysql_alter_table. However, if there is a RENAME + change of a field, or an index, the short cut is not used. - See how `fields` is used to generate the new FRM regarding the structure - of the fields. The same is done for the indices of the table. + See how `create_list` is used to generate the new FRM regarding the + structure of the fields. The same is done for the indices of the table. Important is the fact, that this function tries to do as little work as possible, by finding out whether a intermediate table is needed to copy data into and when finishing the altering to use it as the original table. For this reason the function compare_tables() is called, which decides based on all kind of data how similar are the new and the original - tables. + tables. RETURN VALUES FALSE OK @@ -5391,36 +5697,28 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, */ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, - HA_CREATE_INFO *lex_create_info, + HA_CREATE_INFO *create_info, TABLE_LIST *table_list, - List<create_field> &fields, List<Key> &keys, - uint order_num, ORDER *order, bool ignore, - ALTER_INFO *alter_info, bool do_send_ok) + Alter_info *alter_info, + uint order_num, ORDER *order, bool ignore) { TABLE *table, *new_table= 0, *name_lock= 0; int error= 0; char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN]; char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias; - char index_file[FN_REFLEN], data_file[FN_REFLEN], tablespace[FN_LEN]; + char index_file[FN_REFLEN], data_file[FN_REFLEN]; char path[FN_REFLEN]; char reg_path[FN_REFLEN+1]; ha_rows copied,deleted; - uint db_create_options, used_fields; handlerton *old_db_type, *new_db_type, *save_old_db_type; legacy_db_type table_type; - HA_CREATE_INFO *create_info; frm_type_enum frm_type; - uint need_copy_table= 0; - bool no_table_reopen= FALSE, varchar= FALSE; + enum_alter_table_change_level need_copy_table= ALTER_TABLE_METADATA_ONLY; #ifdef WITH_PARTITION_STORAGE_ENGINE uint fast_alter_partition= 0; bool partition_changed= FALSE; #endif - List<create_field> prepared_create_list; - List<Key> prepared_key_list; bool need_lock_for_indexes= TRUE; - uint db_options= 0; - uint key_count; KEY *key_info_buffer; uint index_drop_count; uint *index_drop_buffer; @@ -5434,6 +5732,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, LINT_INIT(index_add_buffer); LINT_INIT(index_drop_buffer); + /* + Check if we attempt to alter mysql.slow_log or + mysql.general_log table and return an error if + it is the case. + TODO: this design is obsolete and will be removed. + */ if (table_list && table_list->db && table_list->table_name) { int table_kind= 0; @@ -5442,29 +5746,40 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table_list->table_name_length, table_list->table_name, 0); - /* Disable alter of enabled log tables */ - if (table_kind && logger.is_log_table_enabled(table_kind)) + if (table_kind) { - my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER"); - DBUG_RETURN(TRUE); - } + /* Disable alter of enabled log tables */ + if (logger.is_log_table_enabled(table_kind)) + { + my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER"); + DBUG_RETURN(TRUE); + } - /* Disable alter of log tables to unsupported engine */ - if (table_kind && - (lex_create_info->used_fields & HA_CREATE_USED_ENGINE) && - (!lex_create_info->db_type || /* unknown engine */ - !(lex_create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) - { - my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0)); - DBUG_RETURN(TRUE); + /* Disable alter of log tables to unsupported engine */ + if ((create_info->used_fields & HA_CREATE_USED_ENGINE) && + (!create_info->db_type || /* unknown engine */ + !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) + { + my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0)); + DBUG_RETURN(TRUE); + } + +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (alter_info->flags & ALTER_PARTITION) + { + my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table"); + DBUG_RETURN(TRUE); + } +#endif } } + /* + Assign variables table_name, new_name, db, new_db, path, reg_path + to simplify further comparisions: we want to see if it's a RENAME + later just by comparing the pointers, avoiding the need for strcmp. + */ thd->proc_info="init"; - if (!(create_info= copy_create_info(lex_create_info))) - { - DBUG_RETURN(TRUE); - } table_name=table_list->table_name; alias= (lower_case_table_names == 2) ? table_list->alias : table_name; db=table_list->db; @@ -5473,7 +5788,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0); build_table_filename(path, sizeof(path), db, table_name, "", 0); - used_fields=create_info->used_fields; mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE); @@ -5485,10 +5799,22 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, "/", table_name, reg_ext, NullS); (void) unpack_filename(new_name_buff, new_name_buff); - if (lower_case_table_names != 2) - my_casedn_str(files_charset_info, new_name_buff); + /* + If this is just a rename of a view, short cut to the + following scenario: 1) lock LOCK_open 2) do a RENAME + 2) unlock LOCK_open. + This is a copy-paste added to make sure + ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled + as an independent branch in mysql_execute_command. The need + for a copy-paste arose because the main code flow of ALTER TABLE + ... RENAME tries to use open_ltable, which does not work for views + (open_ltable was never modified to merge table lists of child tables + into the main table list, like open_tables does). + This code is wrong and will be removed, please do not copy. + */ frm_type= mysql_frm_type(thd, new_name_buff, &table_type); /* Rename a view */ + /* Sic: there is a race here */ if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME)) { /* @@ -5534,18 +5860,6 @@ view_err: DBUG_RETURN(TRUE); table->use_all_columns(); - List_iterator<Alter_drop> drop_it(alter_info->drop_list); - List_iterator<create_field> def_it(fields); - List_iterator<Alter_column> alter_it(alter_info->alter_list); - List<create_field> create_list; // Add new fields here - List<Key> key_list; // Add new keys here - List_iterator<create_field> find_it(create_list); - List_iterator<Key> key_it(keys); - List_iterator<create_field> field_it(create_list); - List<key_part_spec> key_parts; - - KEY *key_info=table->key_info; - /* Check that we are not trying to rename to an existing table */ if (new_name) { @@ -5628,14 +5942,17 @@ view_err: create_info->db_type= old_db_type; } -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type, - &partition_changed, &fast_alter_partition)) - goto err; -#endif if (check_engine(thd, new_name, create_info)) goto err; new_db_type= create_info->db_type; + + if (new_db_type != old_db_type && + !table->file->can_switch_engines()) + { + my_error(ER_ROW_IS_REFERENCED, MYF(0)); + goto err; + } + if (create_info->row_type == ROW_TYPE_NOT_USED) create_info->row_type= table->s->row_type; @@ -5670,6 +5987,7 @@ view_err: VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); VOID(pthread_mutex_unlock(&LOCK_open)); + DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000);); error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; @@ -5750,8 +6068,7 @@ view_err: if (!error) { write_bin_log(thd, TRUE, thd->query, thd->query_length); - if (do_send_ok) - send_ok(thd); + send_ok(thd); } else if (error > 0) { @@ -5766,387 +6083,54 @@ view_err: DBUG_RETURN(error); } - /* We have to do full alter table */ + /* We have to do full alter table. */ - /* Let new create options override the old ones */ - if (!(used_fields & HA_CREATE_USED_MIN_ROWS)) - create_info->min_rows= table->s->min_rows; - if (!(used_fields & HA_CREATE_USED_MAX_ROWS)) - create_info->max_rows= table->s->max_rows; - if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) - create_info->avg_row_length= table->s->avg_row_length; - if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) - create_info->default_table_charset= table->s->table_charset; - if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field) - { - /* Table has an autoincrement, copy value to new table */ - table->file->info(HA_STATUS_AUTO); - create_info->auto_increment_value= table->file->stats.auto_increment_value; - } - if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) - create_info->key_block_size= table->s->key_block_size; - - if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY) - { - /* - Regular alter table of disk stored table (no tablespace/storage change) - Copy tablespace name - */ - if ((table->file->get_tablespace_name(thd, tablespace, FN_LEN))) - create_info->tablespace= tablespace; - } - restore_record(table, s->default_values); // Empty record for DEFAULT - create_field *def; - - /* - First collect all fields from table which isn't in drop_list - */ - - Field **f_ptr,*field; - for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) - { - if (field->type() == MYSQL_TYPE_STRING) - varchar= TRUE; - /* Check if field should be dropped */ - Alter_drop *drop; - drop_it.rewind(); - while ((drop=drop_it++)) - { - if (drop->type == Alter_drop::COLUMN && - !my_strcasecmp(system_charset_info,field->field_name, drop->name)) - { - /* Reset auto_increment value if it was dropped */ - if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && - !(used_fields & HA_CREATE_USED_AUTO)) - { - create_info->auto_increment_value=0; - create_info->used_fields|=HA_CREATE_USED_AUTO; - } - break; - } - } - if (drop) - { - drop_it.remove(); - continue; - } - /* Check if field is changed */ - def_it.rewind(); - while ((def=def_it++)) - { - if (def->change && - !my_strcasecmp(system_charset_info,field->field_name, def->change)) - break; - } - if (def) - { // Field is changed - def->field=field; - if (!def->after) - { - create_list.push_back(def); - def_it.remove(); - } - } - else - { - /* - This field was not dropped and not changed, add it to the list - for the new table. - */ - create_list.push_back(def=new create_field(field,field)); - alter_it.rewind(); // Change default if ALTER - Alter_column *alter; - while ((alter=alter_it++)) - { - if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) - break; - } - if (alter) - { - if (def->sql_type == MYSQL_TYPE_BLOB) - { - my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); - goto err; - } - if ((def->def=alter->def)) // Use new default - def->flags&= ~NO_DEFAULT_VALUE_FLAG; - else - def->flags|= NO_DEFAULT_VALUE_FLAG; - alter_it.remove(); - } - } - } - def_it.rewind(); - while ((def=def_it++)) // Add new columns - { - if (def->change && ! def->field) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name); - goto err; - } - if (!def->after) - create_list.push_back(def); - else if (def->after == first_keyword) - create_list.push_front(def); - else - { - create_field *find; - find_it.rewind(); - while ((find=find_it++)) // Add new columns - { - if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) - break; - } - if (!find) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name); - goto err; - } - find_it.after(def); // Put element after this - } - } - if (alter_info->alter_list.elements) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), - alter_info->alter_list.head()->name, table_name); - goto err; - } - if (!create_list.elements) - { - my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS), - MYF(0)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type, + &partition_changed, &fast_alter_partition)) goto err; - } - +#endif /* - Collect all keys which isn't in drop list. Add only those - for which some fields exists. + If the old table had partitions and we are doing ALTER TABLE ... + engine= <new_engine>, the new table must preserve the original + partitioning. That means that the new engine is still the + partitioning engine, not the engine specified in the parser. + This is discovered in prep_alter_part_table, which in such case + updates create_info->db_type. + Now we need to update the stack copy of create_info->db_type, + as otherwise we won't be able to correctly move the files of the + temporary table to the result table files. */ + new_db_type= create_info->db_type; - for (uint i=0 ; i < table->s->keys ; i++,key_info++) - { - char *key_name= key_info->name; - Alter_drop *drop; - drop_it.rewind(); - while ((drop=drop_it++)) - { - if (drop->type == Alter_drop::KEY && - !my_strcasecmp(system_charset_info,key_name, drop->name)) - break; - } - if (drop) - { - drop_it.remove(); - continue; - } - - KEY_PART_INFO *key_part= key_info->key_part; - key_parts.empty(); - for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) - { - if (!key_part->field) - continue; // Wrong field (from UNIREG) - const char *key_part_name=key_part->field->field_name; - create_field *cfield; - field_it.rewind(); - while ((cfield=field_it++)) - { - if (cfield->change) - { - if (!my_strcasecmp(system_charset_info, key_part_name, - cfield->change)) - break; - } - else if (!my_strcasecmp(system_charset_info, - key_part_name, cfield->field_name)) - break; - } - if (!cfield) - continue; // Field is removed - uint key_part_length=key_part->length; - if (cfield->field) // Not new field - { - /* - If the field can't have only a part used in a key according to its - new type, or should not be used partially according to its - previous type, or the field length is less than the key part - length, unset the key part length. - - We also unset the key part length if it is the same as the - old field's length, so the whole new field will be used. - - BLOBs may have cfield->length == 0, which is why we test it before - checking whether cfield->length < key_part_length (in chars). - */ - if (!Field::type_can_have_key_part(cfield->field->type()) || - !Field::type_can_have_key_part(cfield->sql_type) || - /* spatial keys can't have sub-key length */ - (key_info->flags & HA_SPATIAL) || - (cfield->field->field_length == key_part_length && - !f_is_blob(key_part->key_type)) || - (cfield->length && (cfield->length < key_part_length / - key_part->field->charset()->mbmaxlen))) - key_part_length= 0; // Use whole field - } - key_part_length /= key_part->field->charset()->mbmaxlen; - key_parts.push_back(new key_part_spec(cfield->field_name, - key_part_length)); - } - if (key_parts.elements) - { - KEY_CREATE_INFO key_create_info; - bzero((char*) &key_create_info, sizeof(key_create_info)); - - key_create_info.algorithm= key_info->algorithm; - if (key_info->flags & HA_USES_BLOCK_SIZE) - key_create_info.block_size= key_info->block_size; - if (key_info->flags & HA_USES_PARSER) - key_create_info.parser_name= *key_info->parser_name; - - key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : - (key_info->flags & HA_NOSAME ? - (!my_strcasecmp(system_charset_info, - key_name, primary_key_name) ? - Key::PRIMARY : Key::UNIQUE) : - (key_info->flags & HA_FULLTEXT ? - Key::FULLTEXT : Key::MULTIPLE)), - key_name, - &key_create_info, - test(key_info->flags & HA_GENERATED_KEY), - key_parts)); - } - } - { - Key *key; - while ((key=key_it++)) // Add new keys - { - if (key->type != Key::FOREIGN_KEY) - key_list.push_back(key); - if (key->name && - !my_strcasecmp(system_charset_info,key->name,primary_key_name)) - { - my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); - goto err; - } - } - } - - if (alter_info->drop_list.elements) - { - my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), - alter_info->drop_list.head()->name); - goto err; - } - if (alter_info->alter_list.elements) - { - my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), - alter_info->alter_list.head()->name); + if (mysql_prepare_alter_table(thd, table, create_info, alter_info)) goto err; - } - - db_create_options= table->s->db_create_options & ~(HA_OPTION_PACK_RECORD); - my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix, - current_pid, thd->thread_id); - /* Safety fix for innodb */ - if (lower_case_table_names) - my_casedn_str(files_charset_info, tmp_name); - if (new_db_type != old_db_type && !table->file->can_switch_engines()) { - my_error(ER_ROW_IS_REFERENCED, MYF(0)); - goto err; - } - create_info->db_type=new_db_type; - if (!create_info->comment.str) - { - create_info->comment.str= table->s->comment.str; - create_info->comment.length= table->s->comment.length; - } - - table->file->update_create_info(create_info); - if ((create_info->table_options & - (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) || - (used_fields & HA_CREATE_USED_PACK_KEYS)) - db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); - if (create_info->table_options & - (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM)) - db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM); - if (create_info->table_options & - (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE)) - db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE | - HA_OPTION_NO_DELAY_KEY_WRITE); - create_info->table_options|= db_create_options; - - if (table->s->tmp_table) - create_info->options|=HA_LEX_CREATE_TMP_TABLE; + + need_copy_table= alter_info->change_level; set_table_default_charset(thd, create_info, db); - { - /* - For some purposes we need prepared table structures and translated - key descriptions with proper default key name assignment. - - Unfortunately, mysql_prepare_table() modifies the field and key - lists. mysql_create_table() needs the unmodified lists. Hence, we - need to copy the lists and all their elements. The lists contain - pointers to the elements only. - - We cannot copy conditionally because the partition code always - needs prepared lists and compare_tables() needs them and is almost - always called. - */ - - /* Copy fields. */ - List_iterator<create_field> prep_field_it(create_list); - create_field *prep_field; - while ((prep_field= prep_field_it++)) - prepared_create_list.push_back(new create_field(*prep_field)); - - /* Copy keys and key parts. */ - List_iterator<Key> prep_key_it(key_list); - Key *prep_key; - while ((prep_key= prep_key_it++)) - { - List<key_part_spec> prep_columns; - List_iterator<key_part_spec> prep_col_it(prep_key->columns); - key_part_spec *prep_col; - - while ((prep_col= prep_col_it++)) - prep_columns.push_back(new key_part_spec(*prep_col)); - prepared_key_list.push_back(new Key(prep_key->type, prep_key->name, - &prep_key->key_create_info, - prep_key->generated, prep_columns)); - } - - /* Create the prepared information. */ - if (mysql_prepare_table(thd, create_info, &prepared_create_list, - &prepared_key_list, - (table->s->tmp_table != NO_TMP_TABLE), &db_options, - table->file, &key_info_buffer, &key_count, 0)) - goto err; - } - if (thd->variables.old_alter_table || (table->s->db_type() != create_info->db_type) #ifdef WITH_PARTITION_STORAGE_ENGINE || partition_changed #endif ) - need_copy_table= 1; + need_copy_table= ALTER_TABLE_DATA_CHANGED; else { - /* Try to optimize ALTER TABLE. Allocate result buffers. */ - if (! (index_drop_buffer= - (uint*) thd->alloc(sizeof(uint) * table->s->keys)) || - ! (index_add_buffer= - (uint*) thd->alloc(sizeof(uint) * prepared_key_list.elements))) - goto err; + enum_alter_table_change_level need_copy_table_res; /* Check how much the tables differ. */ - need_copy_table= compare_tables(table, &prepared_create_list, - key_info_buffer, key_count, - create_info, alter_info, order_num, - index_drop_buffer, &index_drop_count, - index_add_buffer, &index_add_count, - varchar); + if (compare_tables(table, alter_info, + create_info, order_num, + &need_copy_table_res, + &key_info_buffer, + &index_drop_buffer, &index_drop_count, + &index_add_buffer, &index_add_count)) + goto err; + + if (need_copy_table == ALTER_TABLE_METADATA_ONLY) + need_copy_table= need_copy_table_res; } /* @@ -6244,13 +6228,13 @@ view_err: if ((alter_flags & needed_online_flags) == needed_online_flags) { /* All required online flags are present. */ - need_copy_table= 0; + need_copy_table= ALTER_TABLE_METADATA_ONLY; need_lock_for_indexes= FALSE; } else if ((alter_flags & needed_fast_flags) == needed_fast_flags) { /* All required fast flags are present. */ - need_copy_table= 0; + need_copy_table= ALTER_TABLE_METADATA_ONLY; } } DBUG_PRINT("info", ("need_copy_table: %u need_lock: %d", @@ -6262,7 +6246,7 @@ view_err: alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|... so that ALTER TABLE won't break when somebody will add new flag */ - if (!need_copy_table) + if (need_copy_table == ALTER_TABLE_METADATA_ONLY) create_info->frm_only= 1; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -6271,12 +6255,17 @@ view_err: DBUG_ASSERT(!name_lock); DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, create_info, table_list, - &create_list, &key_list, db, table_name, fast_alter_partition)); } #endif + my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix, + current_pid, thd->thread_id); + /* Safety fix for innodb */ + if (lower_case_table_names) + my_casedn_str(files_charset_info, tmp_name); + /* Handling of symlinked tables: If no rename: @@ -6330,14 +6319,15 @@ view_err: */ tmp_disable_binlog(thd); error= mysql_create_table_no_lock(thd, new_db, tmp_name, - create_info, create_list, - key_list, 1, 0, 0); + create_info, + alter_info, + 1, 0); reenable_binlog(thd); if (error) goto err; /* Open the table if we need to copy the data. */ - if (need_copy_table) + if (need_copy_table != ALTER_TABLE_METADATA_ONLY) { if (table->s->tmp_table) { @@ -6372,9 +6362,11 @@ view_err: /* We don't want update TIMESTAMP fields during ALTER TABLE. */ new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; - error=copy_data_between_tables(table, new_table, create_list, ignore, - order_num, order, &copied, &deleted, - alter_info->keys_onoff); + error= copy_data_between_tables(table, new_table, + alter_info->create_list, ignore, + order_num, order, &copied, &deleted, + alter_info->keys_onoff, + alter_info->error_if_not_empty); } else { @@ -6385,6 +6377,9 @@ view_err: alter_info->keys_onoff); table->file->ha_external_lock(thd, F_UNLCK); VOID(pthread_mutex_unlock(&LOCK_open)); + error= ha_commit_stmt(thd); + if (ha_commit(thd)) + error= 1; } thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -6404,26 +6399,6 @@ view_err: table->file->prepare_for_alter(); if (index_add_count) { -#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892 - if (! need_lock_for_indexes) - { - /* Downgrade the write lock. */ - mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE); - } - - /* Create a new .frm file for crash recovery. */ - /* TODO: Must set INDEX_TO_BE_ADDED flags in the frm file. */ - VOID(pthread_mutex_lock(&LOCK_open)); - error= (mysql_create_frm(thd, reg_path, db, table_name, - create_info, prepared_create_list, key_count, - key_info_buffer, table->file) || - table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG, - create_info)); - VOID(pthread_mutex_unlock(&LOCK_open)); - if (error) - goto err1; -#endif - /* The add_index() method takes an array of KEY structs. */ key_info= (KEY*) thd->alloc(sizeof(KEY) * index_add_count); key= key_info; @@ -6456,36 +6431,6 @@ view_err: if (index_drop_count) { -#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892 - /* Create a new .frm file for crash recovery. */ - /* TODO: Must set INDEX_IS_ADDED in the frm file. */ - /* TODO: Must set INDEX_TO_BE_DROPPED in the frm file. */ - VOID(pthread_mutex_lock(&LOCK_open)); - error= (mysql_create_frm(thd, reg_path, db, table_name, - create_info, prepared_create_list, key_count, - key_info_buffer, table->file) || - table->file->create_handler_files(reg_path, NULL, CHF_INDEX_FLAG, - create_info)); - VOID(pthread_mutex_unlock(&LOCK_open)); - if (error) - goto err1; - - if (! need_lock_for_indexes) - { - LOCK_PARAM_TYPE lpt; - - lpt.thd= thd; - lpt.table= table; - lpt.db= db; - lpt.table_name= table_name; - lpt.create_info= create_info; - lpt.create_list= &create_list; - lpt.key_count= key_count; - lpt.key_info_buffer= key_info_buffer; - abort_and_upgrade_lock(lpt); - } -#endif - /* The prepare_drop_index() method takes an array of key numbers. */ key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count); keyno_p= key_numbers; @@ -6505,27 +6450,6 @@ view_err: goto err1; } -#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020 - if (! need_lock_for_indexes) - { - /* Downgrade the lock again. */ - if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ) - { - LOCK_PARAM_TYPE lpt; - - lpt.thd= thd; - lpt.table= table; - lpt.db= db; - lpt.table_name= table_name; - lpt.create_info= create_info; - lpt.create_list= &create_list; - lpt.key_count= key_count; - lpt.key_info_buffer= key_info_buffer; - close_open_tables_and_downgrade(lpt); - } - } -#endif - /* Tell the handler to finally drop the indexes. */ if ((error= table->file->final_drop_index(table))) { @@ -6574,7 +6498,7 @@ view_err: { /* Close the intermediate table that will be the new table */ intern_close_table(new_table); - my_free((gptr) new_table,MYF(0)); + my_free(new_table,MYF(0)); } VOID(pthread_mutex_lock(&LOCK_open)); if (error) @@ -6585,9 +6509,19 @@ view_err: } /* - Data is copied. Now we rename the old table to a temp name, - rename the new one to the old name, remove all entries about the old table - from the cache, free all locks, close the old table and remove it. + Data is copied. Now we: + 1) Wait until all other threads close old version of table. + 2) Close instances of table open by this thread and replace them + with exclusive name-locks. + 3) Rename the old table to a temp name, rename the new one to the + old name. + 4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME + we reopen new version of table. + 5) Write statement to the binary log. + 6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we + remove name-locks from list of open tables and table cache. + 7) If we are not not under LOCK TABLES we rely on close_thread_tables() + call to remove name-locks from table cache and list of open table. */ thd->proc_info="rename result table"; @@ -6596,38 +6530,8 @@ view_err: if (lower_case_table_names) my_casedn_str(files_charset_info, old_name); -#if !defined( __WIN__) - if (table->file->has_transactions()) -#endif - { - /* - Win32 and InnoDB can't drop a table that is in use, so we must - close the original table before doing the rename - */ - close_cached_table(thd, table); - table=0; // Marker that table is closed - no_table_reopen= TRUE; - } -#if !defined( __WIN__) - else - table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore -#endif - - if (new_name != table_name || new_db != db) - { - /* - Check that there is no table with target name. See the - comment describing code for 'simple' ALTER TABLE ... RENAME. - */ - if (!access(new_name_buff,F_OK)) - { - error=1; - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); - VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; - } - } + wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DELETE); + close_data_files_and_morph_locks(thd, db, table_name); error=0; save_old_db_type= old_db_type; @@ -6645,18 +6549,22 @@ view_err: table is renamed and the SE is also changed, then an intermediate table is created and the additional call will not take place. */ - if (!need_copy_table) - new_db_type=old_db_type= NULL; // this type cannot happen in regular ALTER + if (need_copy_table == ALTER_TABLE_METADATA_ONLY) + { + DBUG_ASSERT(new_db_type == old_db_type); + /* This type cannot happen in regular ALTER. */ + new_db_type= old_db_type= NULL; + } if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP)) { error=1; VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); } - else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db, + else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) || (new_name != table_name || new_db != db) && // we also do rename - (need_copy_table || + (need_copy_table != ALTER_TABLE_METADATA_ONLY || mysql_rename_table(save_old_db_type, db, table_name, new_db, new_alias, NO_FRM_RENAME)) && Table_triggers_list::change_table_name(thd, db, table_name, @@ -6672,137 +6580,68 @@ view_err: if (error) { - /* - This shouldn't happen. We solve this the safe way by - closing the locked table. - */ - if (table) - { - close_cached_table(thd,table); - } - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; + /* This shouldn't happen. But let us play it safe. */ + goto err_with_placeholders; } - if (! need_copy_table) + + if (need_copy_table == ALTER_TABLE_METADATA_ONLY) { - bool needs_unlink= FALSE; - if (! table) - { - if (new_name != table_name || new_db != db) - { - table_list->alias= new_name; - table_list->table_name= new_name; - table_list->table_name_length= strlen(new_name); - table_list->db= new_db; - table_list->db_length= strlen(new_db); - } - else - { - /* - TODO: Creation of name-lock placeholder here is a temporary - work-around. Long term we should change close_cached_table() call - which we invoke before table renaming operation in such way that - it will leave placeholders for table in table cache/THD::open_tables - list. By doing this we will be able easily reopen and relock these - tables later and therefore behave under LOCK TABLES in the same way - on all platforms. - */ - char key[MAX_DBKEY_LENGTH]; - uint key_length; - key_length= create_table_def_key(thd, key, table_list, 0); - if (!(name_lock= table_cache_insert_placeholder(thd, key, - key_length))) - { - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; - } - name_lock->next= thd->open_tables; - thd->open_tables= name_lock; - } + /* + Now we have to inform handler that new .FRM file is in place. + To do this we need to obtain a handler object for it. + */ + TABLE *t_table; + if (new_name != table_name || new_db != db) + { + table_list->alias= new_name; + table_list->table_name= new_name; + table_list->table_name_length= strlen(new_name); + table_list->db= new_db; + table_list->db_length= strlen(new_db); table_list->table= name_lock; if (reopen_name_locked_table(thd, table_list, FALSE)) - { - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; - } - table= table_list->table; - /* - We can't rely on later close_cached_table() calls to close - this instance of the table since it was not properly locked. - */ - needs_unlink= TRUE; + goto err_with_placeholders; + t_table= table_list->table; } - /* Tell the handler that a new frm file is in place. */ - if (table->file->create_handler_files(path, NULL, CHF_INDEX_FLAG, - create_info)) + else { - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; + if (reopen_table(table)) + goto err_with_placeholders; + t_table= table; } - if (needs_unlink) + /* Tell the handler that a new frm file is in place. */ + if (t_table->file->create_handler_files(path, NULL, CHF_INDEX_FLAG, + create_info)) + goto err_with_placeholders; + if (thd->locked_tables && new_name == table_name && new_db == db) { - unlink_open_table(thd, table, FALSE); - table= name_lock= 0; + /* + We are going to reopen table down on the road, so we have to restore + state of the TABLE object which we used for obtaining of handler + object to make it suitable for reopening. + */ + DBUG_ASSERT(t_table == table); + table->open_placeholder= 1; + close_handle_and_leave_table_as_lock(table); } } - if (thd->lock || new_name != table_name || no_table_reopen) // True if WIN32 - { - /* - Not table locking or alter table with rename. - Free locks and remove old table - */ - if (table) - { - close_cached_table(thd,table); - } - VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); - } - else - { - /* - Using LOCK TABLES without rename. - This code is never executed on WIN32! - Remove old renamed table, reopen table and get new locks - */ - if (table) - { - VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file - /* Mark in-use copies old */ - remove_table_from_cache(thd,db,table_name,RTFC_NO_FLAG); - /* end threads waiting on lock */ - mysql_lock_abort(thd,table, TRUE); - } - VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); - if (close_data_tables(thd,db,table_name) || - reopen_tables(thd,1,0)) - { // This shouldn't happen - if (table) - { - close_cached_table(thd,table); // Remove lock for table - } - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; - } - } - VOID(pthread_mutex_unlock(&LOCK_open)); - broadcast_refresh(); - /* - The ALTER TABLE is always in its own transaction. - Commit must not be called while LOCK_open is locked. It could call - wait_if_global_read_lock(), which could create a deadlock if called - with LOCK_open. - */ - if (!committed) + VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); + + if (thd->locked_tables && new_name == table_name && new_db == db) { - error = ha_commit_stmt(thd); - if (ha_commit(thd)) - error=1; + thd->in_lock_tables= 1; + error= reopen_tables(thd, 1, 0); + thd->in_lock_tables= 0; if (error) - goto err; + goto err_with_placeholders; } + VOID(pthread_mutex_unlock(&LOCK_open)); + thd->proc_info="end"; + DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000);); + ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE, thd->query, thd->query_length, db, table_name); @@ -6812,7 +6651,7 @@ view_err: (create_info->options & HA_LEX_CREATE_TMP_TABLE))); write_bin_log(thd, TRUE, thd->query, thd->query_length); - if (ha_check_storage_engine_flag(old_db_type,HTON_FLUSH_AFTER_RENAME)) + if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME)) { /* For the alter table to be properly flushed to the logs, we @@ -6820,12 +6659,13 @@ view_err: shutdown. */ char path[FN_REFLEN]; + TABLE *t_table; build_table_filename(path, sizeof(path), new_db, table_name, "", 0); - table=open_temporary_table(thd, path, new_db, tmp_name,0); - if (table) + t_table= open_temporary_table(thd, path, new_db, tmp_name, 0); + if (t_table) { - intern_close_table(table); - my_free((char*) table, MYF(0)); + intern_close_table(t_table); + my_free(t_table, MYF(0)); } else sql_print_warning("Could not open table %s.%s after rename\n", @@ -6835,9 +6675,16 @@ view_err: table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); - if (name_lock) + if (thd->locked_tables && (new_name != table_name || new_db != db)) { + /* + If are we under LOCK TABLES and did ALTER TABLE with RENAME we need + to remove placeholders for the old table and for the target table + from the list of open tables and table cache. If we are not under + LOCK TABLES we can rely on close_thread_tables() doing this job. + */ pthread_mutex_lock(&LOCK_open); + unlink_open_table(thd, table, FALSE); unlink_open_table(thd, name_lock, FALSE); pthread_mutex_unlock(&LOCK_open); } @@ -6846,8 +6693,7 @@ end_temporary: my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), (ulong) (copied + deleted), (ulong) deleted, (ulong) thd->cuted_fields); - if (do_send_ok) - send_ok(thd,copied+deleted,0L,tmp_name); + send_ok(thd, copied + deleted, 0L, tmp_name); thd->some_tables_deleted=0; DBUG_RETURN(FALSE); @@ -6861,6 +6707,38 @@ err1: VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); err: + /* + No default value was provided for a DATE/DATETIME field, the + current sql_mode doesn't allow the '0000-00-00' value and + the table to be altered isn't empty. + Report error here. + */ + if (alter_info->error_if_not_empty && thd->row_count) + { + const char *f_val= 0; + enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE; + switch (alter_info->datetime_field->sql_type) + { + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + f_val= "0000-00-00"; + t_type= MYSQL_TIMESTAMP_DATE; + break; + case MYSQL_TYPE_DATETIME: + f_val= "0000-00-00 00:00:00"; + t_type= MYSQL_TIMESTAMP_DATETIME; + break; + default: + /* Shouldn't get here. */ + DBUG_ASSERT(0); + } + bool save_abort_on_warning= thd->abort_on_warning; + thd->abort_on_warning= TRUE; + make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + f_val, strlength(f_val), t_type, + alter_info->datetime_field->field_name); + thd->abort_on_warning= save_abort_on_warning; + } if (name_lock) { pthread_mutex_lock(&LOCK_open); @@ -6868,17 +6746,30 @@ err: pthread_mutex_unlock(&LOCK_open); } DBUG_RETURN(TRUE); + +err_with_placeholders: + /* + An error happened while we were holding exclusive name-lock on table + being altered. To be safe under LOCK TABLES we should remove placeholders + from list of open tables list and table cache. + */ + unlink_open_table(thd, table, FALSE); + if (name_lock) + unlink_open_table(thd, name_lock, FALSE); + VOID(pthread_mutex_unlock(&LOCK_open)); + DBUG_RETURN(TRUE); } /* mysql_alter_table */ static int copy_data_between_tables(TABLE *from,TABLE *to, - List<create_field> &create, + List<Create_field> &create, bool ignore, uint order_num, ORDER *order, ha_rows *copied, ha_rows *deleted, - enum enum_enable_or_disable keys_onoff) + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty) { int error; Copy_field *copy,*copy_end; @@ -6926,8 +6817,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, save_sql_mode= thd->variables.sql_mode; - List_iterator<create_field> it(create); - create_field *def; + List_iterator<Create_field> it(create); + Create_field *def; copy_end=copy; for (Field **ptr=to->field ; *ptr ; ptr++) { @@ -6990,6 +6881,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, break; } thd->row_count++; + /* Return error if source table isn't empty. */ + if (error_if_not_empty) + { + error= 1; + break; + } if (to->next_number_field) { if (auto_increment_field_copied) @@ -7003,7 +6900,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, copy_ptr->do_copy(copy_ptr); } prev_insert_id= to->file->next_insert_id; - error=to->file->write_row((byte*) to->record[0]); + error=to->file->write_row(to->record[0]); to->auto_increment_field_not_null= FALSE; if (error) { @@ -7045,8 +6942,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, } to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); - ha_enable_transaction(thd,TRUE); - + if (ha_enable_transaction(thd, TRUE)) + { + error= 1; + goto err; + } + /* Ensure that the new table is saved properly to disk so that we can do a rename @@ -7076,31 +6977,26 @@ copy_data_between_tables(TABLE *from,TABLE *to, mysql_recreate_table() thd Thread handler tables Tables to recreate - do_send_ok If we should send_ok() or leave it to caller RETURN Like mysql_alter_table(). */ -bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, - bool do_send_ok) +bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list) { - DBUG_ENTER("mysql_recreate_table"); - LEX *lex= thd->lex; HA_CREATE_INFO create_info; - lex->create_list.empty(); - lex->key_list.empty(); - lex->col_list.empty(); - lex->alter_info.reset(); - bzero((char*) &create_info,sizeof(create_info)); + Alter_info alter_info; + + DBUG_ENTER("mysql_recreate_table"); + + bzero((char*) &create_info, sizeof(create_info)); create_info.db_type= 0; create_info.row_type=ROW_TYPE_NOT_USED; create_info.default_table_charset=default_charset_info; /* Force alter table to recreate table */ - lex->alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); + alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, - table_list, lex->create_list, - lex->key_list, 0, (ORDER *) 0, - 0, &lex->alter_info, do_send_ok)); + table_list, &alter_info, 0, + (ORDER *) 0, 0)); } @@ -7189,10 +7085,10 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, { String tmp; f->val_str(&tmp); - row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length()); + row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length()); } else - row_crc= my_checksum(row_crc, (byte*) f->ptr, + row_crc= my_checksum(row_crc, f->ptr, f->pack_length()); } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index d7573b42c5f..5bd01eea68c 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -349,7 +349,7 @@ static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data, table_lock_info.lock_text=text; // lock_type is also obtainable from THR_LOCK_DATA table_lock_info.type=table->reginfo.lock_type; - VOID(push_dynamic(ar,(gptr) &table_lock_info)); + VOID(push_dynamic(ar,(uchar*) &table_lock_info)); } } } @@ -394,7 +394,7 @@ static void display_table_locks(void) VOID(pthread_mutex_unlock(&THR_LOCK_lock)); if (!saved_table_locks.elements) goto end; - qsort((gptr) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare); + qsort((uchar*) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare); freeze_size(&saved_table_locks); puts("\nThread database.table_name Locked/Waiting Lock_type\n"); @@ -508,7 +508,9 @@ Next alarm time: %lu\n", display_table_locks(); fflush(stdout); my_checkmalloc(); + fprintf(stdout,"\nBegin safemalloc memory dump:\n"); // tag needed for test suite TERMINATE(stdout); // Write malloc information + fprintf(stdout,"\nEnd safemalloc memory dump.\n"); #ifdef HAVE_MALLINFO struct mallinfo info= mallinfo(); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index bdfcef23101..7433a3f45cd 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -23,7 +23,7 @@ static const LEX_STRING triggers_file_type= { C_STRING_WITH_LEN("TRIGGERS") }; -const char * const triggers_file_ext= ".TRG"; +const char * const TRG_EXT= ".TRG"; /* Table of .TRG file field descriptors. @@ -79,7 +79,7 @@ struct st_trigname static const LEX_STRING trigname_file_type= { C_STRING_WITH_LEN("TRIGGERNAME") }; -const char * const trigname_file_ext= ".TRN"; +const char * const TRN_EXT= ".TRN"; static File_option trigname_file_parameters[]= { @@ -114,7 +114,7 @@ public: Handle_old_incorrect_sql_modes_hook(char *file_path) :path(file_path) {}; - virtual bool process_unknown_string(char *&unknown_key, gptr base, + virtual bool process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, char *end); }; @@ -125,13 +125,14 @@ public: LEX_STRING *trigger_table_arg) :path(file_path), trigger_table_value(trigger_table_arg) {}; - virtual bool process_unknown_string(char *&unknown_key, gptr base, + virtual bool process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, char *end); private: char *path; LEX_STRING *trigger_table_value; }; + /* Create or drop trigger for table. @@ -463,14 +464,14 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, sql_create_definition_file() files handles renaming and backup of older versions */ - file.length= build_table_filename(file_buff, FN_REFLEN-1, + file.length= build_table_filename(file_buff, FN_REFLEN - 1, tables->db, tables->table_name, - triggers_file_ext, 0); + TRG_EXT, 0); file.str= file_buff; trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, tables->db, lex->spname->m_name.str, - trigname_file_ext, 0); + TRN_EXT, 0); trigname_file.str= trigname_buff; /* Use the filesystem to enforce trigger namespace constraints. */ @@ -484,7 +485,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, trigname.trigger_table.length= tables->table_name_length; if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, - (gptr)&trigname, trigname_file_parameters, 0)) + (uchar*)&trigname, trigname_file_parameters, 0)) return 1; /* @@ -563,10 +564,13 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, append_definer(thd, stmt_query, &definer_user, &definer_host); } - stmt_query->append(thd->lex->stmt_definition_begin, - (char *) thd->lex->sphead->m_body_begin - - thd->lex->stmt_definition_begin + - thd->lex->sphead->m_body.length); + LEX_STRING stmt_definition; + stmt_definition.str= (char*) thd->lex->stmt_definition_begin; + stmt_definition.length= thd->lex->stmt_definition_end + - thd->lex->stmt_definition_begin; + trim_whitespace(thd->charset(), & stmt_definition); + + stmt_query->append(stmt_definition.str, stmt_definition.length); trg_def->str= stmt_query->c_ptr(); trg_def->length= stmt_query->length(); @@ -574,7 +578,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, /* Create trigger definition file. */ if (!sql_create_definition_file(NULL, &file, &triggers_file_type, - (gptr)this, triggers_file_parameters, 0)) + (uchar*)this, triggers_file_parameters, 0)) return 0; err_with_cleanup: @@ -601,7 +605,7 @@ err_with_cleanup: static bool rm_trigger_file(char *path, const char *db, const char *table_name) { - build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext, 0); + build_table_filename(path, FN_REFLEN-1, db, table_name, TRG_EXT, 0); return my_delete(path, MYF(MY_WME)); } @@ -624,8 +628,7 @@ static bool rm_trigger_file(char *path, const char *db, static bool rm_trigname_file(char *path, const char *db, const char *trigger_name) { - build_table_filename(path, FN_REFLEN-1, - db, trigger_name, trigname_file_ext, 0); + build_table_filename(path, FN_REFLEN - 1, db, trigger_name, TRN_EXT, 0); return my_delete(path, MYF(MY_WME)); } @@ -650,11 +653,11 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, char file_buff[FN_REFLEN]; LEX_STRING file; - file.length= build_table_filename(file_buff, FN_REFLEN-1, db, table_name, - triggers_file_ext, 0); + file.length= build_table_filename(file_buff, FN_REFLEN - 1, db, table_name, + TRG_EXT, 0); file.str= file_buff; return sql_create_definition_file(NULL, &file, &triggers_file_type, - (gptr)triggers, triggers_file_parameters, + (uchar*)triggers, triggers_file_parameters, 0); } @@ -831,8 +834,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_ENTER("Table_triggers_list::check_n_load"); - path.length= build_table_filename(path_buff, FN_REFLEN-1, - db, table_name, triggers_file_ext, 0); + path.length= build_table_filename(path_buff, FN_REFLEN - 1, + db, table_name, TRG_EXT, 0); path.str= path_buff; // QQ: should we analyze errno somehow ? @@ -865,7 +868,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, triggers->definition_modes_list.empty(); triggers->definers_list.empty(); - if (parser->parse((gptr)triggers, &table->mem_root, + if (parser->parse((uchar*)triggers, &table->mem_root, triggers_file_parameters, TRG_NUM_REQUIRED_PARAMETERS, &sql_modes_hook)) @@ -945,7 +948,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, of routines used by statement. */ triggers->sroutines_key.length= 1+strlen(db)+1+strlen(table_name)+1; - if (!(triggers->sroutines_key.str= + if (!(triggers->sroutines_key.str= (char*) alloc_root(&table->mem_root, triggers->sroutines_key.length))) DBUG_RETURN(1); triggers->sroutines_key.str[0]= TYPE_ENUM_TRIGGER; @@ -978,12 +981,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, thd->variables.sql_mode= (ulong)*trg_sql_mode; Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length); - thd->m_lip= &lip; lex_start(thd); thd->spcont= 0; - int err= MYSQLparse((void *)thd); - if (err || thd->is_fatal_error) + if (parse_sql(thd, &lip)) { /* Currently sphead is always deleted in case of a parse error */ DBUG_ASSERT(lex.sphead == 0); @@ -1032,7 +1033,11 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, if (!(on_table_name= (LEX_STRING*) alloc_root(&table->mem_root, sizeof(LEX_STRING)))) goto err_with_lex_cleanup; - *on_table_name= lex.ident; + + on_table_name->str= (char*) lex.raw_trg_on_table_name_begin; + on_table_name->length= lex.raw_trg_on_table_name_end + - lex.raw_trg_on_table_name_begin; + if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root)) goto err_with_lex_cleanup; @@ -1101,7 +1106,7 @@ err_with_lex_cleanup: be merged into .FRM anyway. */ my_error(ER_WRONG_OBJECT, MYF(0), - table_name, triggers_file_ext+1, "TRIGGER"); + table_name, TRG_EXT + 1, "TRIGGER"); DBUG_RETURN(1); } @@ -1161,83 +1166,66 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, } -/* +/** Find trigger's table from trigger identifier and add it to the statement table list. - SYNOPSIS - mysql_table_for_trigger() - thd - current thread context - trig - identifier for trigger - if_exists - treat a not existing trigger as a warning if TRUE - table - pointer to TABLE_LIST object for the table trigger (output) - - RETURN VALUE - 0 Success - 1 Error + @param[in] thd Thread context. + @param[in] trg_name Trigger name. + @param[in] if_exists TRUE if SQL statement contains "IF EXISTS" clause. + That means a warning instead of error should be + thrown if trigger with given name does not exist. + @param[out] table Pointer to TABLE_LIST object for the + table trigger. + + @return Operation status + @retval FALSE On success. + @retval TRUE Otherwise. */ -int -add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists, - TABLE_LIST **table) +bool add_table_for_trigger(THD *thd, + sp_name *trg_name, + bool if_exists, + TABLE_LIST **table) { LEX *lex= thd->lex; - char path_buff[FN_REFLEN]; - LEX_STRING path; - File_parser *parser; - struct st_trigname trigname; - Handle_old_incorrect_trigger_table_hook trigger_table_hook( - path_buff, &trigname.trigger_table); - + char trn_path_buff[FN_REFLEN]; + LEX_STRING trn_path= { trn_path_buff, 0 }; + LEX_STRING tbl_name; + DBUG_ENTER("add_table_for_trigger"); - DBUG_ASSERT(table != NULL); - path.length= build_table_filename(path_buff, FN_REFLEN-1, - trig->m_db.str, trig->m_name.str, - trigname_file_ext, 0); - path.str= path_buff; + build_trn_path(thd, trg_name, &trn_path); - if (access(path_buff, F_OK)) + if (check_trn_exists(&trn_path)) { if (if_exists) { push_warning_printf(thd, - MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_TRG_DOES_NOT_EXIST, - ER(ER_TRG_DOES_NOT_EXIST)); + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TRG_DOES_NOT_EXIST, + ER(ER_TRG_DOES_NOT_EXIST)); + *table= NULL; - DBUG_RETURN(0); + + DBUG_RETURN(FALSE); } my_error(ER_TRG_DOES_NOT_EXIST, MYF(0)); - DBUG_RETURN(1); - } - - if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1))) - DBUG_RETURN(1); - - if (!is_equal(&trigname_file_type, parser->type())) - { - my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1, - "TRIGGERNAME"); - DBUG_RETURN(1); + DBUG_RETURN(TRUE); } - if (parser->parse((gptr)&trigname, thd->mem_root, - trigname_file_parameters, 1, - &trigger_table_hook)) - DBUG_RETURN(1); + if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name)) + DBUG_RETURN(TRUE); /* We need to reset statement table list to be PS/SP friendly. */ lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; - *table= sp_add_to_query_tables(thd, lex, trig->m_db.str, - trigname.trigger_table.str, TL_IGNORE); - if (! *table) - DBUG_RETURN(1); + *table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str, + tbl_name.str, TL_IGNORE); - DBUG_RETURN(0); + DBUG_RETURN(*table ? FALSE : TRUE); } @@ -1348,7 +1336,12 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, /* Construct CREATE TRIGGER statement with new table name. */ buff.length(0); + + /* WARNING: 'on_table_name' is supposed to point inside 'def' */ + DBUG_ASSERT(on_table_name->str > def->str); + DBUG_ASSERT(on_table_name->str < (def->str + def->length)); before_on_len= on_table_name->str - def->str; + buff.append(def->str, before_on_len); buff.append(STRING_WITH_LEN("ON ")); append_identifier(thd, &buff, new_table_name->str, new_table_name->length); @@ -1360,8 +1353,8 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, It is OK to allocate some memory on table's MEM_ROOT since this table instance will be thrown out at the end of rename anyway. */ - new_def.str= memdup_root(&trigger_table->mem_root, buff.ptr(), - buff.length()); + new_def.str= (char*) memdup_root(&trigger_table->mem_root, buff.ptr(), + buff.length()); new_def.length= buff.length(); on_table_name->str= new_def.str + before_on_len; on_table_name->length= on_q_table_name_len; @@ -1416,13 +1409,13 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, { trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, db_name, trigger->str, - trigname_file_ext, 0); + TRN_EXT, 0); trigname_file.str= trigname_buff; trigname.trigger_table= *new_table_name; if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, - (gptr)&trigname, trigname_file_parameters, + (uchar*)&trigname, trigname_file_parameters, 0)) return trigger; } @@ -1525,77 +1518,54 @@ end: } -bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, - trg_action_time_type time_type, - bool old_row_is_record1) -{ - bool err_status= FALSE; - sp_head *sp_trigger= bodies[event][time_type]; - - if (sp_trigger) - { - Sub_statement_state statement_state; - - if (old_row_is_record1) - { - old_field= record1_field; - new_field= trigger_table->field; - } - else - { - new_field= record1_field; - old_field= trigger_table->field; - } -#ifndef NO_EMBEDDED_ACCESS_CHECKS - Security_context *sctx= &sp_trigger->m_security_ctx; - Security_context *save_ctx= NULL; - +/** + Execute trigger for given (event, time) pair. - if (sp_trigger->m_chistics->suid != SP_IS_NOT_SUID && - sctx->change_security_context(thd, - &sp_trigger->m_definer_user, - &sp_trigger->m_definer_host, - &sp_trigger->m_db, - &save_ctx)) - return TRUE; + The operation executes trigger for the specified event (insert, update, + delete) and time (after, before) if it is set. - /* - Fetch information about table-level privileges to GRANT_INFO structure for - subject table. Check of privileges that will use it and information about - column-level privileges will happen in Item_trigger_field::fix_fields(). - */ + @param thd + @param event + @param time_type, + @param old_row_is_record1 - fill_effective_table_privileges(thd, - &subject_table_grants[event][time_type], - trigger_table->s->db.str, - trigger_table->s->table_name.str); + @return Error status. + @retval FALSE on success. + @retval TRUE on error. +*/ - /* Check that the definer has TRIGGER privilege on the subject table. */ +bool Table_triggers_list::process_triggers(THD *thd, + trg_event_type event, + trg_action_time_type time_type, + bool old_row_is_record1) +{ + bool err_status; + Sub_statement_state statement_state; - if (!(subject_table_grants[event][time_type].privilege & TRIGGER_ACL)) - { - char priv_desc[128]; - get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL); + if (!bodies[event][time_type]) + return FALSE; - my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc, - thd->security_ctx->priv_user, thd->security_ctx->host_or_ip, - trigger_table->s->table_name.str); + if (old_row_is_record1) + { + old_field= record1_field; + new_field= trigger_table->field; + } + else + { + new_field= record1_field; + old_field= trigger_table->field; + } - sctx->restore_security_context(thd, save_ctx); - return TRUE; - } -#endif // NO_EMBEDDED_ACCESS_CHECKS + thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER); - thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER); - err_status= sp_trigger->execute_trigger - (thd, trigger_table->s->db.str, trigger_table->s->table_name.str, - &subject_table_grants[event][time_type]); - thd->restore_sub_statement_state(&statement_state); + err_status= + bodies[event][time_type]->execute_trigger( + thd, + &trigger_table->s->db, + &trigger_table->s->table_name, + &subject_table_grants[event][time_type]); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - sctx->restore_security_context(thd, save_ctx); -#endif // NO_EMBEDDED_ACCESS_CHECKS - } + thd->restore_sub_statement_state(&statement_state); return err_status; } @@ -1663,7 +1633,7 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) bool Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, - gptr base, + uchar* base, MEM_ROOT *mem_root, char *end) { @@ -1706,7 +1676,7 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, bool Handle_old_incorrect_trigger_table_hook:: -process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root, +process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, char *end) { DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string"); @@ -1737,3 +1707,95 @@ process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root, } DBUG_RETURN(FALSE); } + + +/** + Contruct path to TRN-file. + + @param thd[in] Thread context. + @param trg_name[in] Trigger name. + @param trn_path[out] Variable to store constructed path +*/ + +void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path) +{ + /* Construct path to the TRN-file. */ + + trn_path->length= build_table_filename(trn_path->str, + FN_REFLEN - 1, + trg_name->m_db.str, + trg_name->m_name.str, + TRN_EXT, + 0); +} + + +/** + Check if TRN-file exists. + + @return + @retval TRUE if TRN-file does not exist. + @retval FALSE if TRN-file exists. +*/ + +bool check_trn_exists(const LEX_STRING *trn_path) +{ + return access(trn_path->str, F_OK) != 0; +} + + +/** + Retrieve table name for given trigger. + + @param thd[in] Thread context. + @param trg_name[in] Trigger name. + @param trn_path[in] Path to the corresponding TRN-file. + @param tbl_name[out] Variable to store retrieved table name. + + @return Error status. + @retval FALSE on success. + @retval TRUE if table name could not be retrieved. +*/ + +bool load_table_name_for_trigger(THD *thd, + const sp_name *trg_name, + const LEX_STRING *trn_path, + LEX_STRING *tbl_name) +{ + File_parser *parser; + struct st_trigname trn_data; + + Handle_old_incorrect_trigger_table_hook trigger_table_hook( + trn_path->str, + &trn_data.trigger_table); + + DBUG_ENTER("load_table_name_for_trigger"); + + /* Parse the TRN-file. */ + + if (!(parser= sql_parse_prepare(trn_path, thd->mem_root, TRUE))) + DBUG_RETURN(TRUE); + + if (!is_equal(&trigname_file_type, parser->type())) + { + my_error(ER_WRONG_OBJECT, MYF(0), + trg_name->m_name.str, + TRN_EXT + 1, + "TRIGGERNAME"); + + DBUG_RETURN(TRUE); + } + + if (parser->parse((uchar*) &trn_data, thd->mem_root, + trigname_file_parameters, 1, + &trigger_table_hook)) + DBUG_RETURN(TRUE); + + /* Copy trigger table name. */ + + *tbl_name= trn_data.trigger_table; + + /* That's all. */ + + DBUG_RETURN(FALSE); +} diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 7d99dd811cd..c305efb5029 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -17,7 +17,7 @@ /* This class holds all information about triggers of table. - QQ: Will it be merged into TABLE in future ? + QQ: Will it be merged into TABLE in the future ? */ class Table_triggers_list: public Sql_alloc @@ -143,6 +143,17 @@ private: extern const LEX_STRING trg_action_time_type_names[]; extern const LEX_STRING trg_event_type_names[]; -int -add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists, - TABLE_LIST **table); +bool add_table_for_trigger(THD *thd, + sp_name *trg_name, + bool continue_if_not_exist, + TABLE_LIST **table); + +void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path); + +bool check_trn_exists(const LEX_STRING *trn_path); + +bool load_table_name_for_trigger(THD *thd, + const sp_name *trg_name, + const LEX_STRING *trn_path, + LEX_STRING *tbl_name); + diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 505f7a9a765..20ce614f361 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -92,12 +92,12 @@ static char *init_syms(udf_func *tmp, char *nm) } -extern "C" byte* get_hash_key(const byte *buff,uint *length, +extern "C" uchar* get_hash_key(const uchar *buff, size_t *length, my_bool not_used __attribute__((unused))) { udf_func *udf=(udf_func*) buff; *length=(uint) udf->name.length; - return (byte*) udf->name.str; + return (uchar*) udf->name.str; } @@ -137,7 +137,7 @@ void udf_init() new_thd->store_globals(); new_thd->set_db(db, sizeof(db)-1); - bzero((gptr) &tables,sizeof(tables)); + bzero((uchar*) &tables,sizeof(tables)); tables.alias= tables.table_name= (char*) "func"; tables.lock_type = TL_READ; tables.db= db; @@ -267,7 +267,7 @@ static void del_udf(udf_func *udf) DBUG_ENTER("del_udf"); if (!--udf->usage_count) { - hash_delete(&udf_hash,(byte*) udf); + hash_delete(&udf_hash,(uchar*) udf); using_udf_functions=udf_hash.records != 0; } else @@ -281,7 +281,7 @@ static void del_udf(udf_func *udf) uint name_length=udf->name.length; udf->name.str=(char*) "*"; udf->name.length=1; - hash_update(&udf_hash,(byte*) udf,(byte*) name,name_length); + hash_update(&udf_hash,(uchar*) udf,(uchar*) name,name_length); } DBUG_VOID_RETURN; } @@ -301,7 +301,7 @@ void free_udf(udf_func *udf) We come here when someone has deleted the udf function while another thread still was using the udf */ - hash_delete(&udf_hash,(byte*) udf); + hash_delete(&udf_hash,(uchar*) udf); using_udf_functions=udf_hash.records != 0; if (!find_udf_dl(udf->dl)) dlclose(udf->dlhandle); @@ -327,7 +327,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used) else rw_rdlock(&THR_LOCK_udf); /* Called during parsing */ - if ((udf=(udf_func*) hash_search(&udf_hash,(byte*) name, + if ((udf=(udf_func*) hash_search(&udf_hash,(uchar*) name, length ? length : (uint) strlen(name)))) { if (!udf->dlhandle) @@ -374,7 +374,7 @@ static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl, tmp->returns = ret; tmp->type = type; tmp->usage_count=1; - if (my_hash_insert(&udf_hash,(byte*) tmp)) + if (my_hash_insert(&udf_hash,(uchar*) tmp)) return 0; using_udf_functions=1; return tmp; @@ -427,7 +427,7 @@ int mysql_create_function(THD *thd,udf_func *udf) thd->clear_current_stmt_binlog_row_based(); rw_wrlock(&THR_LOCK_udf); - if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length))) + if ((hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) { my_error(ER_UDF_EXISTS, MYF(0), udf->name); goto err; @@ -533,7 +533,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) thd->clear_current_stmt_binlog_row_based(); rw_wrlock(&THR_LOCK_udf); - if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str, + if (!(udf=(udf_func*) hash_search(&udf_hash,(uchar*) udf_name->str, (uint) udf_name->length))) { my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str); @@ -557,7 +557,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) table->use_all_columns(); table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin); if (!table->file->index_read_idx(table->record[0], 0, - (byte*) table->field[0]->ptr, HA_WHOLE_KEY, + (uchar*) table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { int error; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index dbae7977d62..c872d3cb241 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -144,8 +144,8 @@ void st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) { thd_arg->lex->current_select= fake_select_lex; - fake_select_lex->table_list.link_in_list((byte *)&result_table_list, - (byte **) + fake_select_lex->table_list.link_in_list((uchar *)&result_table_list, + (uchar **) &result_table_list.next_local); fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table= @@ -162,7 +162,7 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) order=order->next) { (*order->item)->walk(&Item::change_context_processor, 0, - (byte*) &fake_select_lex->context); + (uchar*) &fake_select_lex->context); } } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ef384c30b59..693ba779e5d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -545,8 +545,8 @@ int mysql_update(THD *thd, else { /* Non-batched update */ - error= table->file->ha_update_row((byte*) table->record[1], - (byte*) table->record[0]); + error= table->file->ha_update_row(table->record[1], + table->record[0]); } if (!error) { @@ -621,6 +621,37 @@ int mysql_update(THD *thd, thd->row_count++; } dup_key_found= 0; + + /* + todo bug#27571: to avoid asynchronization of `error' and + `error_code' of binlog event constructor + + The concept, which is a bit different for insert(!), is to + replace `error' assignment with the following lines + + killed_status= thd->killed; // get the status of the volatile + + Notice: thd->killed is type of "state" whereas the lhs has + "status" the suffix which translates according to WordNet: a state + at a particular time - at the time of the end of per-row loop in + our case. Binlogging ops are conducted with the status. + + error= (killed_status == THD::NOT_KILLED)? error : 1; + + which applies to most mysql_$query functions. + Event's constructor will accept `killed_status' as an argument: + + Query_log_event qinfo(..., killed_status); + + thd->killed might be changed after killed_status had got cached and this + won't affect binlogging event but other effects remain. + + Open issue: In a case the error happened not because of KILLED - + and then KILLED was caught later still within the loop - we shall + do something to avoid binlogging of incorrect ER_SERVER_SHUTDOWN + error_code. + */ + if (thd->killed && !error) error= 1; // Aborted else if (will_batch && @@ -936,7 +967,7 @@ reopen_tables: if (check_access(thd, want_privilege, tl->db, &tl->grant.privilege, 0, 0, test(tl->schema_table)) || - (grant_option && check_grant(thd, want_privilege, tl, 0, 1, 0))) + check_grant(thd, want_privilege, tl, 0, 1, 0)) DBUG_RETURN(TRUE); } } @@ -1038,6 +1069,7 @@ bool mysql_multi_update(THD *thd, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex) { multi_update *result; + bool res; DBUG_ENTER("mysql_multi_update"); if (!(result= new multi_update(table_list, @@ -1052,7 +1084,7 @@ bool mysql_multi_update(THD *thd, MODE_STRICT_ALL_TABLES)); List<Item> total_list; - (void) mysql_select(thd, &select_lex->ref_pointer_array, + res= mysql_select(thd, &select_lex->ref_pointer_array, table_list, select_lex->with_wild, total_list, conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, @@ -1060,6 +1092,15 @@ bool mysql_multi_update(THD *thd, options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE, result, unit, select_lex); + DBUG_PRINT("info",("res: %d report_error: %d", res, + thd->net.report_error)); + res|= thd->net.report_error; + if (unlikely(res)) + { + /* If we had a another error reported earlier then this will be ignored */ + result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR)); + result->abort(); + } delete result; thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -1093,6 +1134,7 @@ int multi_update::prepare(List<Item> ¬_used_values, List_iterator_fast<Item> field_it(*fields); List_iterator_fast<Item> value_it(*values); uint i, max_fields; + uint leaf_table_count= 0; DBUG_ENTER("multi_update::prepare"); thd->count_cuted_fields= CHECK_FIELD_WARN; @@ -1126,13 +1168,14 @@ int multi_update::prepare(List<Item> ¬_used_values, { /* TODO: add support of view of join support */ TABLE *table=table_ref->table; + leaf_table_count++; if (tables_to_update & table->map) { TABLE_LIST *tl= (TABLE_LIST*) thd->memdup((char*) table_ref, sizeof(*tl)); if (!tl) DBUG_RETURN(1); - update.link_in_list((byte*) tl, (byte**) &tl->next_local); + update.link_in_list((uchar*) tl, (uchar**) &tl->next_local); tl->shared= table_count++; table->no_keyread=1; table->covering_keys.clear_all(); @@ -1187,7 +1230,7 @@ int multi_update::prepare(List<Item> ¬_used_values, /* Allocate copy fields */ max_fields=0; for (i=0 ; i < table_count ; i++) - set_if_bigger(max_fields, fields_for_table[i]->elements); + set_if_bigger(max_fields, fields_for_table[i]->elements + leaf_table_count); copy_field= new Copy_field[max_fields]; DBUG_RETURN(thd->is_fatal_error != 0); } @@ -1278,13 +1321,22 @@ multi_update::initialize_tables(JOIN *join) trans_safe= transactional_tables= main_table->file->has_transactions(); table_to_update= 0; + /* Any update has at least one pair (field, value) */ + DBUG_ASSERT(fields->elements); + /* + Only one table may be modified by UPDATE of an updatable view. + For an updatable view first_table_for_update indicates this + table. + For a regular multi-update it refers to some updated table. + */ + TABLE *first_table_for_update= ((Item_field *) fields->head())->field->table; + /* Create a temporary table for keys to all tables, except main table */ for (table_ref= update_tables; table_ref; table_ref= table_ref->next_local) { TABLE *table=table_ref->table; uint cnt= table_ref->shared; - Item_field *ifield; - List<Item> temp_fields= *fields_for_table[cnt]; + List<Item> temp_fields; ORDER group; TMP_TABLE_PARAM *tmp_param; @@ -1301,27 +1353,56 @@ multi_update::initialize_tables(JOIN *join) } table->prepare_for_position(); + if (table == first_table_for_update && table_ref->check_option) + { + table_map unupdated_tables= table_ref->check_option->used_tables() & + ~first_table_for_update->map; + for (TABLE_LIST *tbl_ref =leaves; + unupdated_tables && tbl_ref; + tbl_ref= tbl_ref->next_leaf) + { + if (unupdated_tables & tbl_ref->table->map) + unupdated_tables&= ~tbl_ref->table->map; + else + continue; + if (unupdated_check_opt_tables.push_back(tbl_ref->table)) + DBUG_RETURN(1); + } + } + tmp_param= tmp_table_param+cnt; + /* Create a temporary table to store all fields that are changed for this table. The first field in the temporary table is a pointer to the - original row so that we can find and update it + original row so that we can find and update it. For the updatable + VIEW a few following fields are rowids of tables used in the CHECK + OPTION condition. */ - /* ok to be on stack as this is not referenced outside of this func */ - Field_string offset(table->file->ref_length, 0, "offset", - &my_charset_bin); - offset.init(table); - /* - The field will be converted to varstring when creating tmp table if - table to be updated was created by mysql 4.1. Deny this. - */ - offset.can_alter_field_type= 0; - if (!(ifield= new Item_field(((Field *) &offset)))) - DBUG_RETURN(1); - ifield->maybe_null= 0; - if (temp_fields.push_front(ifield)) - DBUG_RETURN(1); + List_iterator_fast<TABLE> tbl_it(unupdated_check_opt_tables); + TABLE *tbl= table; + do + { + Field_string *field= new Field_string(tbl->file->ref_length, 0, + tbl->alias, &my_charset_bin); + if (!field) + DBUG_RETURN(1); + field->init(tbl); + /* + The field will be converted to varstring when creating tmp table if + table to be updated was created by mysql 4.1. Deny this. + */ + field->can_alter_field_type= 0; + Item_field *ifield= new Item_field((Field *) field); + if (!ifield) + DBUG_RETURN(1); + ifield->maybe_null= 0; + if (temp_fields.push_back(ifield)) + DBUG_RETURN(1); + } while ((tbl= tbl_it++)); + + temp_fields.concat(fields_for_table[cnt]); /* Make an unique key over the first field to avoid duplicated updates */ bzero((char*) &group, sizeof(group)); @@ -1370,8 +1451,9 @@ multi_update::~multi_update() if (copy_field) delete [] copy_field; thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting - if (!trans_safe) + if (!trans_safe) // todo: remove since redundant thd->no_trans_update.all= TRUE; + DBUG_ASSERT(trans_safe || thd->no_trans_update.all); } @@ -1460,8 +1542,15 @@ bool multi_update::send_data(List<Item> ¬_used_values) } else { - if (!table->file->has_transactions()) + /* non-transactional or transactional table got modified */ + /* either multi_update class' flag is raised in its branch */ + if (table->file->has_transactions()) + transactional_tables= 1; + else + { + trans_safe= 0; thd->no_trans_update.stmt= TRUE; + } if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)) @@ -1473,11 +1562,26 @@ bool multi_update::send_data(List<Item> ¬_used_values) { int error; TABLE *tmp_table= tmp_tables[offset]; - table->file->position(table->record[0]); - fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1); - /* Store pointer to row */ - memcpy((char*) tmp_table->field[0]->ptr, - (char*) table->file->ref, table->file->ref_length); + /* + For updatable VIEW store rowid of the updated table and + rowids of tables used in the CHECK OPTION condition. + */ + uint field_num= 0; + List_iterator_fast<TABLE> tbl_it(unupdated_check_opt_tables); + TABLE *tbl= table; + do + { + tbl->file->position(tbl->record[0]); + memcpy((char*) tmp_table->field[field_num]->ptr, + (char*) tbl->file->ref, tbl->file->ref_length); + field_num++; + } while ((tbl= tbl_it++)); + + /* Store regular updated fields in the row. */ + fill_record(thd, + tmp_table->field + 1 + unupdated_check_opt_tables.elements, + *values_for_table[offset], 1); + /* Write row, ignoring duplicated updates to a row */ error= tmp_table->file->ha_write_row(tmp_table->record[0]); if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) @@ -1503,8 +1607,8 @@ void multi_update::send_error(uint errcode,const char *err) my_error(errcode, MYF(0), err); /* If nothing updated return */ - if (!updated) - return; + if (updated == 0) /* the counter might be reset in send_eof */ + return; /* and then the query has been binlogged */ /* Something already updated so we have to invalidate cache */ query_cache_invalidate3(thd, update_tables, 1); @@ -1515,11 +1619,43 @@ void multi_update::send_error(uint errcode,const char *err) */ if (trans_safe) - ha_rollback_stmt(thd); - else if (do_update && table_count > 1) { - /* Add warning here */ - VOID(do_updates(0)); + DBUG_ASSERT(transactional_tables); + (void) ha_autocommit_or_rollback(thd, 1); + } + else + { + DBUG_ASSERT(thd->no_trans_update.stmt); + if (do_update && table_count > 1) + { + /* Add warning here */ + /* + todo/fixme: do_update() is never called with the arg 1. + should it change the signature to become argless? + */ + VOID(do_updates(0)); + } + } + if (thd->no_trans_update.stmt) + { + /* + The query has to binlog because there's a modified non-transactional table + either from the query's list or via a stored routine: bug#13270,23333 + */ + if (mysql_bin_log.is_open()) + { + thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query, thd->query_length, + transactional_tables, FALSE); + } + if (!trans_safe) + thd->no_trans_update.all= TRUE; + } + DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt); + + if (transactional_tables) + { + (void) ha_autocommit_or_rollback(thd, 1); } } @@ -1527,9 +1663,10 @@ void multi_update::send_error(uint errcode,const char *err) int multi_update::do_updates(bool from_send_error) { TABLE_LIST *cur_table; - int local_error; + int local_error= 0; ha_rows org_updated; TABLE *table, *tmp_table; + List_iterator_fast<TABLE> check_opt_it(unupdated_check_opt_tables); DBUG_ENTER("do_updates"); do_update= 0; // Don't retry this function @@ -1537,8 +1674,8 @@ int multi_update::do_updates(bool from_send_error) DBUG_RETURN(0); for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { - byte *ref_pos; bool can_compare_record; + uint offset= cur_table->shared; table = cur_table->table; if (table == table_to_update) @@ -1549,11 +1686,20 @@ int multi_update::do_updates(bool from_send_error) (void) table->file->ha_rnd_init(0); table->file->extra(HA_EXTRA_NO_CACHE); + check_opt_it.rewind(); + while(TABLE *tbl= check_opt_it++) + { + if (tbl->file->ha_rnd_init(1)) + goto err; + tbl->file->extra(HA_EXTRA_CACHE); + } + /* Setup copy functions to copy fields from temporary table */ - List_iterator_fast<Item> field_it(*fields_for_table[cur_table->shared]); - Field **field= tmp_table->field+1; // Skip row pointer + List_iterator_fast<Item> field_it(*fields_for_table[offset]); + Field **field= tmp_table->field + + 1 + unupdated_check_opt_tables.elements; // Skip row pointers Copy_field *copy_field_ptr= copy_field, *copy_field_end; for ( ; *field ; field++) { @@ -1570,7 +1716,6 @@ int multi_update::do_updates(bool from_send_error) bitmap_is_subset(table->write_set, table->read_set)); - ref_pos= (byte*) tmp_table->field[0]->ptr; for (;;) { if (thd->killed && trans_safe) @@ -1583,8 +1728,20 @@ int multi_update::do_updates(bool from_send_error) continue; // May happen on dup key goto err; } - if ((local_error= table->file->rnd_pos(table->record[0], ref_pos))) - goto err; + + /* call rnd_pos() using rowids from temporary table */ + check_opt_it.rewind(); + TABLE *tbl= table; + uint field_num= 0; + do + { + if((local_error= + tbl->file->rnd_pos(tbl->record[0], + (uchar *) tmp_table->field[field_num]->ptr))) + goto err; + field_num++; + } while((tbl= check_opt_it++)); + table->status|= STATUS_UPDATED; store_record(table,record[1]); @@ -1629,12 +1786,19 @@ int multi_update::do_updates(bool from_send_error) if (updated != org_updated) { if (table->file->has_transactions()) - transactional_tables= 1; + transactional_tables= 1; else - trans_safe= 0; // Can't do safe rollback + { + trans_safe= 0; // Can't do safe rollback + thd->no_trans_update.stmt= TRUE; + } } (void) table->file->ha_rnd_end(); (void) tmp_table->file->ha_rnd_end(); + check_opt_it.rewind(); + while (TABLE *tbl= check_opt_it++) + tbl->file->ha_rnd_end(); + } DBUG_RETURN(0); @@ -1648,13 +1812,19 @@ err: err2: (void) table->file->ha_rnd_end(); (void) tmp_table->file->ha_rnd_end(); + check_opt_it.rewind(); + while (TABLE *tbl= check_opt_it++) + tbl->file->ha_rnd_end(); if (updated != org_updated) { if (table->file->has_transactions()) transactional_tables= 1; else + { trans_safe= 0; + thd->no_trans_update.stmt= TRUE; + } } DBUG_RETURN(1); } @@ -1684,14 +1854,20 @@ bool multi_update::send_eof() Write the SQL statement to the binlog if we updated rows and we succeeded or if we updated some non transactional tables. + + The query has to binlog because there's a modified non-transactional table + either from the query's list or via a stored routine: bug#13270,23333 */ - if ((local_error == 0) || (updated && !trans_safe)) + DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt); + if (local_error == 0 || thd->no_trans_update.stmt) { if (mysql_bin_log.is_open()) { if (local_error == 0) thd->clear_error(); + else + updated= 0; /* if there's an error binlog it here not in ::send_error */ if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, transactional_tables, FALSE) && @@ -1700,7 +1876,7 @@ bool multi_update::send_eof() local_error= 1; // Rollback update } } - if (!transactional_tables) + if (!trans_safe) thd->no_trans_update.all= TRUE; } @@ -1712,7 +1888,7 @@ bool multi_update::send_eof() if (local_error > 0) // if the above log write did not fail ... { - /* Safety: If we haven't got an error before (should not happen) */ + /* Safety: If we haven't got an error before (can happen in do_updates) */ my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update", MYF(0)); return TRUE; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index bf48cd0094a..58e74d132d5 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -322,11 +322,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, */ if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege, 0, 0, is_schema_db(view->db)) || - grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) || + check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) || (mode != VIEW_CREATE_NEW && (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 0, 0, is_schema_db(view->db)) || - grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) + check_grant(thd, DROP_ACL, view, 0, 1, 0)))) { res= TRUE; goto err; @@ -379,7 +379,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { if (check_access(thd, SELECT_ACL, tbl->db, &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || - grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) + check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) { res= TRUE; goto err; @@ -690,8 +690,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, char md5[MD5_BUFF_LENGTH]; bool can_be_merged; char dir_buff[FN_REFLEN], path_buff[FN_REFLEN]; - const char *endp; LEX_STRING dir, file, path; + int error= 0; DBUG_ENTER("mysql_register_view"); /* print query */ @@ -702,9 +702,58 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, lex->unit.print(&str); thd->variables.sql_mode|= sql_mode; } - str.append('\0'); DBUG_PRINT("info", ("View: %s", str.ptr())); + /* fill structure */ + view->query.str= str.c_ptr_safe(); + view->query.length= str.length(); + + view->source.str= (char*) thd->lex->create_view_select_start; + view->source.length= (thd->lex->create_view_select_end + - thd->lex->create_view_select_start); + trim_whitespace(thd->charset(), & view->source); + + view->file_version= 1; + view->calc_md5(md5); + view->md5.str= md5; + view->md5.length= 32; + can_be_merged= lex->can_be_merged(); + if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE && + !lex->can_be_merged()) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE, + ER(ER_WARN_VIEW_MERGE)); + lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; + } + view->algorithm= lex->create_view_algorithm; + view->definer.user= lex->definer->user; + view->definer.host= lex->definer->host; + view->view_suid= lex->create_view_suid; + view->with_check= lex->create_view_check; + if ((view->updatable_view= (can_be_merged && + view->algorithm != VIEW_ALGORITHM_TMPTABLE))) + { + /* TODO: change here when we will support UNIONs */ + for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first; + tbl; + tbl= tbl->next_local) + { + if ((tbl->view && !tbl->updatable_view) || tbl->schema_table) + { + view->updatable_view= 0; + break; + } + for (TABLE_LIST *up= tbl; up; up= up->embedding) + { + if (up->outer_join) + { + view->updatable_view= 0; + goto loop_out; + } + } + } + } +loop_out: /* print file name */ dir.length= build_table_filename(dir_buff, sizeof(dir_buff), view->db, "", "", 0); @@ -736,16 +785,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, if (mode == VIEW_CREATE_NEW) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); - DBUG_RETURN(-1); + error= -1; + goto err; } if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) - DBUG_RETURN(1); + { + error= 1; + goto err; + } if (!parser->ok() || !is_equal(&view_type, parser->type())) { my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); - DBUG_RETURN(-1); + error= -1; + goto err; } /* @@ -754,70 +808,25 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, TODO: read dependence list, too, to process cascade/restrict TODO: special cascade/restrict procedure for alter? */ - if (parser->parse((gptr)view, thd->mem_root, + if (parser->parse((uchar*)view, thd->mem_root, view_parameters + revision_number_position, 1, &file_parser_dummy_hook)) { - DBUG_RETURN(thd->net.report_error? -1 : 0); + error= thd->net.report_error? -1 : 0; + goto err; } } else - { + { if (mode == VIEW_ALTER) { my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); - DBUG_RETURN(-1); - } - } - } - /* fill structure */ - view->query.str= (char*)str.ptr(); - view->query.length= str.length()-1; // we do not need last \0 - view->source.str= thd->query + thd->lex->create_view_select_start; - endp= view->source.str; - endp= skip_rear_comments(endp, thd->query + thd->query_length); - view->source.length= endp - view->source.str; - view->file_version= 1; - view->calc_md5(md5); - view->md5.str= md5; - view->md5.length= 32; - can_be_merged= lex->can_be_merged(); - if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE && - !lex->can_be_merged()) - { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE, - ER(ER_WARN_VIEW_MERGE)); - lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; - } - view->algorithm= lex->create_view_algorithm; - view->definer.user= lex->definer->user; - view->definer.host= lex->definer->host; - view->view_suid= lex->create_view_suid; - view->with_check= lex->create_view_check; - if ((view->updatable_view= (can_be_merged && - view->algorithm != VIEW_ALGORITHM_TMPTABLE))) - { - /* TODO: change here when we will support UNIONs */ - for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first; - tbl; - tbl= tbl->next_local) - { - if ((tbl->view && !tbl->updatable_view) || tbl->schema_table) - { - view->updatable_view= 0; - break; - } - for (TABLE_LIST *up= tbl; up; up= up->embedding) - { - if (up->outer_join) - { - view->updatable_view= 0; - goto loop_out; - } + error= -1; + goto err; } } } -loop_out: + /* Check that table of main select do not used in subqueries. @@ -842,15 +851,23 @@ loop_out: !view->updatable_view) { my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name); - DBUG_RETURN(-1); + error= -1; + goto err; } if (sql_create_definition_file(&dir, &file, view_file_type, - (gptr)view, view_parameters, num_view_backups)) + (uchar*)view, view_parameters, num_view_backups)) { - DBUG_RETURN(thd->net.report_error? -1 : 1); + error= thd->net.report_error? -1 : 1; + goto err; } DBUG_RETURN(0); +err: + view->query.str= NULL; + view->query.length= 0; + view->md5.str= NULL; + view->md5.length= 0; + DBUG_RETURN(error); } @@ -876,7 +893,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, LEX *old_lex, *lex; Query_arena *arena, backup; TABLE_LIST *top_view= table->top_table(); - int res; + bool res; bool result, view_is_mergeable; TABLE_LIST *view_main_select_tables; DBUG_ENTER("mysql_make_view"); @@ -945,7 +962,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, TODO: when VIEWs will be stored in cache, table mem_root should be used here */ - if (parser->parse((gptr)table, thd->mem_root, view_parameters, + if (parser->parse((uchar*)table, thd->mem_root, view_parameters, required_view_parameters, &file_parser_dummy_hook)) goto err; @@ -988,7 +1005,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, { Lex_input_stream lip(thd, table->query.str, table->query.length); - thd->m_lip= &lip; lex_start(thd); view_select= &lex->select_lex; view_select->select_number= ++thd->select_number; @@ -1022,7 +1038,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES); CHARSET_INFO *save_cs= thd->variables.character_set_client; thd->variables.character_set_client= system_charset_info; - res= MYSQLparse((void *)thd); + res= parse_sql(thd, &lip); if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) || (old_lex->sql_command == SQLCOM_SHOW_CREATE)) @@ -1031,7 +1047,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, thd->variables.character_set_client= save_cs; thd->variables.sql_mode= save_mode; } - if (!res && !thd->is_fatal_error) + if (!res) { TABLE_LIST *view_tables= lex->query_tables; TABLE_LIST *view_tables_tail= 0; @@ -1118,8 +1134,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, If the view's body needs row-based binlogging (e.g. the VIEW is created from SELECT UUID()), the top statement also needs it. */ - if (lex->binlog_row_based_if_mixed) - old_lex->binlog_row_based_if_mixed= TRUE; + if (lex->is_stmt_unsafe()) + old_lex->set_stmt_unsafe(); view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && lex->can_be_merged()); LINT_INIT(view_main_select_tables); @@ -1488,7 +1504,7 @@ frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) DBUG_RETURN(FRMTYPE_ERROR); - error= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME | MY_NABP)); + error= my_read(file, (uchar*) header, sizeof(header), MYF(MY_WME | MY_NABP)); my_close(file, MYF(MY_WME)); if (error) @@ -1751,7 +1767,7 @@ mysql_rename_view(THD *thd, view_def.view_suid= TRUE; /* get view definition and source */ - if (parser->parse((gptr)&view_def, thd->mem_root, view_parameters, + if (parser->parse((uchar*)&view_def, thd->mem_root, view_parameters, array_elements(view_parameters)-1, &file_parser_dummy_hook)) goto err; @@ -1773,7 +1789,7 @@ mysql_rename_view(THD *thd, file.length= pathstr.length - dir.length; if (sql_create_definition_file(&dir, &file, view_file_type, - (gptr)&view_def, view_parameters, + (uchar*)&view_def, view_parameters, num_view_backups)) { /* restore renamed view in case of error */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 38d9663fa5c..64610893392 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -106,7 +106,7 @@ void my_parse_error(const char *s) THD *thd= current_thd; Lex_input_stream *lip= thd->m_lip; - const char *yytext= lip->tok_start; + const char *yytext= lip->get_tok_start(); /* Push an error into the error stack */ my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s, (yytext ? yytext : ""), @@ -456,7 +456,7 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, List<Item> *item_list; List<String> *string_list; String *string; - key_part_spec *key_part; + Key_part_spec *key_part; TABLE_LIST *table_list; udf_func *udf; LEX_USER *lex_user; @@ -491,7 +491,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there is 287 shift/reduce conflict. We should not introduce + Currently there is 286 shift/reduce conflict. We should not introduce new conflicts any more. */ %expect 286 @@ -1569,8 +1569,7 @@ create: TL_OPTION_UPDATING, TL_WRITE)) MYSQL_YYABORT; - lex->create_list.empty(); - lex->key_list.empty(); + lex->alter_info.reset(); lex->col_list.empty(); lex->change=NullS; bzero((char*) &lex->create_info,sizeof(lex->create_info)); @@ -1579,7 +1578,6 @@ create: lex->create_info.default_table_charset= NULL; lex->name.str= 0; lex->name.length= 0; - lex->like_name= 0; } create2 { @@ -1604,21 +1602,23 @@ create: NULL, TL_OPTION_UPDATING)) MYSQL_YYABORT; - lex->create_list.empty(); - lex->key_list.empty(); + lex->alter_info.reset(); + lex->alter_info.flags= ALTER_ADD_INDEX; lex->col_list.empty(); lex->change=NullS; } '(' key_list ')' key_options { LEX *lex=Lex; + Key *key; if ($2 != Key::FULLTEXT && lex->key_create_info.parser_name.str) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } - lex->key_list.push_back(new Key($2, $4.str, &lex->key_create_info, 0, - lex->col_list)); + key= new Key($2, $4.str, &lex->key_create_info, 0, + lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); } | CREATE DATABASE opt_if_not_exists ident @@ -1872,10 +1872,7 @@ ev_sql_stmt: bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lip->ptr; - - lex->event_parse_data->body_begin= lip->ptr; - + lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_ptr()); } ev_sql_stmt_inner { @@ -1888,7 +1885,7 @@ ev_sql_stmt: lex->sp_chistics.suid= SP_IS_SUID; //always the definer! - lex->event_parse_data->init_body(thd); + lex->event_parse_data->body_changed= TRUE; } ; @@ -1986,6 +1983,7 @@ create_function_tail: LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; sp_head *sp; + const char* tmp_param_begin; /* First check if AGGREGATE was used, in that case it's a @@ -2017,7 +2015,10 @@ create_function_tail: */ $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; thd->client_capabilities &= ~CLIENT_MULTI_QUERIES; - lex->sphead->m_param_begin= lip->tok_start+1; + + tmp_param_begin= lip->get_cpp_tok_start(); + tmp_param_begin++; + lex->sphead->m_param_begin= tmp_param_begin; } sp_fdparam_list ')' { @@ -2025,7 +2026,7 @@ create_function_tail: LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; - lex->sphead->m_param_end= lip->tok_start; + lex->sphead->m_param_end= lip->get_cpp_tok_start(); } RETURNS_SYM { @@ -2065,7 +2066,7 @@ create_function_tail: Lex_input_stream *lip= thd->m_lip; lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lip->tok_start; + lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_tok_start()); } sp_proc_stmt { @@ -2676,7 +2677,7 @@ sp_proc_stmt_statement: Lex_input_stream *lip= thd->m_lip; lex->sphead->reset_lex(thd); - lex->sphead->m_tmp_query= lip->tok_start; + lex->sphead->m_tmp_query= lip->get_tok_start(); } statement { @@ -2709,9 +2710,9 @@ sp_proc_stmt_statement: lex->tok_end otherwise. */ if (yychar == YYEMPTY) - i->m_query.length= lip->ptr - sp->m_tmp_query; + i->m_query.length= lip->get_ptr() - sp->m_tmp_query; else - i->m_query.length= lip->tok_end - sp->m_tmp_query; + i->m_query.length= lip->get_tok_end() - sp->m_tmp_query; i->m_query.str= strmake_root(thd->mem_root, sp->m_tmp_query, i->m_query.length); @@ -3603,27 +3604,15 @@ create2: create3 {} | LIKE table_ident { - THD *thd= YYTHD; - LEX *lex= thd->lex; - if (!(lex->like_name= $2)) - MYSQL_YYABORT; - if ($2->db.str == NULL && - thd->copy_db_to(&($2->db.str), &($2->db.length))) - { + Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE; + if (!Lex->select_lex.add_table_to_list(YYTHD, $2, NULL, 0, TL_READ)) MYSQL_YYABORT; - } } | '(' LIKE table_ident ')' { - THD *thd= YYTHD; - LEX *lex= thd->lex; - if (!(lex->like_name= $3)) - MYSQL_YYABORT; - if ($3->db.str == NULL && - thd->copy_db_to(&($3->db.str), &($3->db.length))) - { + Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE; + if (!Lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0, TL_READ)) MYSQL_YYABORT; - } } ; @@ -3944,7 +3933,7 @@ opt_part_values: /* empty */ { LEX *lex= Lex; - if (!is_partition_management(lex)) + if (! lex->is_partition_management()) { if (lex->part_info->part_type == RANGE_PARTITION) { @@ -3965,7 +3954,7 @@ opt_part_values: | VALUES LESS_SYM THAN_SYM part_func_max { LEX *lex= Lex; - if (!is_partition_management(lex)) + if (! lex->is_partition_management()) { if (Lex->part_info->part_type != RANGE_PARTITION) { @@ -3980,7 +3969,7 @@ opt_part_values: | VALUES IN_SYM '(' part_list_func ')' { LEX *lex= Lex; - if (!is_partition_management(lex)) + if (! lex->is_partition_management()) { if (Lex->part_info->part_type != LIST_PARTITION) { @@ -4344,10 +4333,10 @@ create_table_option: lex->create_info.merge_list= lex->select_lex.table_list; lex->create_info.merge_list.elements--; lex->create_info.merge_list.first= - (byte*) (table_list->next_local); + (uchar*) (table_list->next_local); lex->select_lex.table_list.elements=1; lex->select_lex.table_list.next= - (byte**) &(table_list->next_local); + (uchar**) &(table_list->next_local); table_list->next_local= 0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } @@ -4491,8 +4480,9 @@ key_def: my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } - lex->key_list.push_back(new Key($1,$2, &lex->key_create_info, 0, - lex->col_list)); + Key *key= new Key($1, $2, &lex->key_create_info, 0, + lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint constraint_key_type opt_ident key_alg @@ -4500,24 +4490,27 @@ key_def: { LEX *lex=Lex; const char *key_name= $3 ? $3 : $1; - lex->key_list.push_back(new Key($2, key_name, &lex->key_create_info, 0, - lex->col_list)); + Key *key= new Key($2, key_name, &lex->key_create_info, 0, + lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { LEX *lex=Lex; - lex->key_list.push_back(new foreign_key($4 ? $4:$1, lex->col_list, - $8, - lex->ref_list, - lex->fk_delete_opt, - lex->fk_update_opt, - lex->fk_match_option)); - lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1, - &default_key_create_info, 1, - lex->col_list)); + const char *key_name= $4 ? $4 : $1; + Key *key= new Foreign_key(key_name, lex->col_list, + $8, + lex->ref_list, + lex->fk_delete_opt, + lex->fk_update_opt, + lex->fk_match_option); + lex->alter_info.key_list.push_back(key); + key= new Key(Key::MULTIPLE, key_name, + &default_key_create_info, 1, + lex->col_list); + lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ - /* Only used for ALTER TABLE. Ignored otherwise. */ lex->alter_info.flags|= ALTER_FOREIGN_KEY; } @@ -4933,8 +4926,8 @@ opt_ref_list: | '(' ref_list ')' opt_on_delete {}; ref_list: - ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); } - | ident { Lex->ref_list.push_back(new key_part_spec($1.str)); }; + ref_list ',' ident { Lex->ref_list.push_back(new Key_part_spec($3.str)); } + | ident { Lex->ref_list.push_back(new Key_part_spec($1.str)); }; opt_on_delete: @@ -4948,16 +4941,16 @@ opt_on_delete_list: opt_on_delete_item: ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; } | ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; } - | MATCH FULL { Lex->fk_match_option= foreign_key::FK_MATCH_FULL; } - | MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; } - | MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; }; + | MATCH FULL { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } + | MATCH PARTIAL { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } + | MATCH SIMPLE_SYM { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; }; delete_option: - RESTRICT { $$= (int) foreign_key::FK_OPTION_RESTRICT; } - | CASCADE { $$= (int) foreign_key::FK_OPTION_CASCADE; } - | SET NULL_SYM { $$= (int) foreign_key::FK_OPTION_SET_NULL; } - | NO_SYM ACTION { $$= (int) foreign_key::FK_OPTION_NO_ACTION; } - | SET DEFAULT { $$= (int) foreign_key::FK_OPTION_DEFAULT; }; + RESTRICT { $$= (int) Foreign_key::FK_OPTION_RESTRICT; } + | CASCADE { $$= (int) Foreign_key::FK_OPTION_CASCADE; } + | SET NULL_SYM { $$= (int) Foreign_key::FK_OPTION_SET_NULL; } + | NO_SYM ACTION { $$= (int) Foreign_key::FK_OPTION_NO_ACTION; } + | SET DEFAULT { $$= (int) Foreign_key::FK_OPTION_DEFAULT; }; key_type: key_or_index { $$= Key::MULTIPLE; } @@ -5069,7 +5062,7 @@ key_list: | key_part order_dir { Lex->col_list.push_back($1); }; key_part: - ident { $$=new key_part_spec($1.str); } + ident { $$=new Key_part_spec($1.str); } | ident '(' NUM ')' { int key_part_len= atoi($3.str); @@ -5077,7 +5070,7 @@ key_part: { my_error(ER_KEY_PART_0, MYF(0), $1.str); } - $$=new key_part_spec($1.str,(uint) key_part_len); + $$=new Key_part_spec($1.str,(uint) key_part_len); }; opt_ident: @@ -5108,19 +5101,16 @@ alter: if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING)) MYSQL_YYABORT; - lex->create_list.empty(); - lex->key_list.empty(); + lex->alter_info.reset(); lex->col_list.empty(); lex->select_lex.init_order(); - lex->like_name= 0; lex->select_lex.db= ((TABLE_LIST*) lex->select_lex.table_list.first)->db; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= 0; lex->create_info.default_table_charset= NULL; lex->create_info.row_type= ROW_TYPE_NOT_USED; - lex->alter_info.reset(); - lex->alter_info.flags= 0; + lex->alter_info.reset(); lex->no_write_to_binlog= 0; lex->create_info.storage_media= HA_SM_DEFAULT; } @@ -5581,10 +5571,10 @@ alter_list_item: { THD *thd= YYTHD; LEX *lex= thd->lex; - uint dummy; + size_t dummy; lex->select_lex.db=$3->db.str; if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, &dummy)) + thd->copy_db_to(&lex->select_lex.db, &dummy)) { MYSQL_YYABORT; } @@ -5762,8 +5752,6 @@ restore: RESTORE_SYM table_or_tables { Lex->sql_command = SQLCOM_RESTORE_TABLE; - WARN_DEPRECATED(yythd, "5.2", "RESTORE TABLE", - "MySQL Administrator (mysqldump, mysql)"); } table_list FROM TEXT_STRING_sys { @@ -5774,8 +5762,6 @@ backup: BACKUP_SYM table_or_tables { Lex->sql_command = SQLCOM_BACKUP_TABLE; - WARN_DEPRECATED(yythd, "5.2", "BACKUP TABLE", - "MySQL Administrator (mysqldump, mysql)"); } table_list TO_SYM TEXT_STRING_sys { @@ -6240,14 +6226,14 @@ remember_name: { THD *thd= YYTHD; Lex_input_stream *lip= thd->m_lip; - $$= (char*) lip->tok_start; + $$= (char*) lip->get_cpp_tok_start(); }; remember_end: { THD *thd= YYTHD; Lex_input_stream *lip= thd->m_lip; - $$=(char*) lip->tok_end; + $$= (char*) lip->get_cpp_tok_end(); }; select_item2: @@ -7126,8 +7112,11 @@ opt_distinct: |DISTINCT { $$ = 1; }; opt_gconcat_separator: - /* empty */ { $$ = new (YYTHD->mem_root) String(",",1,default_charset_info); } - |SEPARATOR_SYM text_string { $$ = $2; }; + /* empty */ + { + $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1); + } + | SEPARATOR_SYM text_string { $$ = $2; }; opt_gorder_clause: @@ -7520,7 +7509,8 @@ select_derived2: { LEX *lex= Lex; lex->derived_tables|= DERIVED_SUBQUERY; - if (!lex->expr_allows_subselect) + if (!lex->expr_allows_subselect || + lex->sql_command == (int)SQLCOM_PURGE) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -7911,6 +7901,9 @@ limit_options: ; limit_option: param_marker + { + ((Item_param *) $1)->set_strict_type(INT_RESULT); + } | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); } | NUM { $$= new Item_uint($1.str, $1.length); } @@ -7990,7 +7983,7 @@ procedure_clause: } lex->proc_list.elements=0; lex->proc_list.first=0; - lex->proc_list.next= (byte**) &lex->proc_list.first; + lex->proc_list.next= (uchar**) &lex->proc_list.first; if (add_proc_to_list(lex->thd, new Item_field(&lex-> current_select-> context, @@ -8010,16 +8003,14 @@ procedure_list2: | procedure_item; procedure_item: - remember_name expr + remember_name expr remember_end { THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; if (add_proc_to_list(thd, $2)) MYSQL_YYABORT; if (!$2->name) - $2->set_name($1,(uint) ((char*) lip->tok_end - $1), - thd->charset()); + $2->set_name($1, (uint) ($3 - $1), thd->charset()); } ; @@ -8155,7 +8146,8 @@ drop: { LEX *lex=Lex; lex->sql_command= SQLCOM_DROP_INDEX; - lex->alter_info.drop_list.empty(); + lex->alter_info.reset(); + lex->alter_info.flags= ALTER_DROP_INDEX; lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL, @@ -8305,7 +8297,7 @@ insert_lock_option: insert visible only after the table unlocking but everyone can read table. */ - $$= (Lex->sphead ? TL_WRITE :TL_WRITE_CONCURRENT_INSERT); + $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT); #else $$= TL_WRITE_CONCURRENT_INSERT; #endif @@ -8483,7 +8475,7 @@ insert_update_elem: }; opt_low_priority: - /* empty */ { $$= YYTHD->update_lock_default; } + /* empty */ { $$= TL_WRITE_DEFAULT; } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; /* Delete rows from a table */ @@ -8494,7 +8486,7 @@ delete: LEX *lex= Lex; lex->sql_command= SQLCOM_DELETE; mysql_init_select(lex); - lex->lock_option= lex->thd->update_lock_default; + lex->lock_option= TL_WRITE_DEFAULT; lex->ignore= 0; lex->select_lex.init_order(); } @@ -9056,6 +9048,7 @@ purge: { LEX *lex=Lex; lex->type=0; + lex->sql_command = SQLCOM_PURGE; } purge_options {} ; @@ -9067,7 +9060,6 @@ purge_options: purge_option: TO_SYM TEXT_STRING_sys { - Lex->sql_command = SQLCOM_PURGE; Lex->to_log = $2.str; } | BEFORE_SYM expr @@ -9118,7 +9110,7 @@ load: LOAD DATA_SYM my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA"); MYSQL_YYABORT; } - lex->fname_start= lip->ptr; + lex->fname_start= lip->get_ptr(); } load_data {} @@ -9155,7 +9147,7 @@ load_data: THD *thd= YYTHD; LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; - lex->fname_end= lip->ptr; + lex->fname_end= lip->get_ptr(); } TABLE_SYM table_ident { @@ -9186,7 +9178,7 @@ opt_local: | LOCAL_SYM { $$=1;}; load_data_lock: - /* empty */ { $$= YYTHD->update_lock_default; } + /* empty */ { $$= TL_WRITE_DEFAULT; } | CONCURRENT { #ifdef HAVE_QUERY_CACHE @@ -9194,7 +9186,7 @@ load_data_lock: Ignore this option in SP to avoid problem with query cache */ if (Lex->sphead != 0) - $$= YYTHD->update_lock_default; + $$= TL_WRITE_DEFAULT; else #endif $$= TL_WRITE_CONCURRENT_INSERT; @@ -9344,7 +9336,7 @@ param_marker: my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); MYSQL_YYABORT; } - item= new Item_param((uint) (lip->tok_start - thd->query)); + item= new Item_param((uint) (lip->get_tok_start() - thd->query)); if (!($$= item) || lex->param_list.push_back(item)) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); @@ -9477,7 +9469,7 @@ simple_ident: Item_splocal *splocal; splocal= new Item_splocal($1, spv->offset, spv->type, - lip->tok_start_prev - + lip->get_tok_start_prev() - lex->sphead->m_tmp_query); #ifndef DBUG_OFF if (splocal) @@ -9560,8 +9552,9 @@ simple_ident_q: Let us add this item to list of all Item_trigger_field objects in trigger. */ - lex->trg_table_fields.link_in_list((byte *)trg_fld, - (byte**)&trg_fld->next_trg_field); + lex->trg_table_fields.link_in_list((uchar*) trg_fld, + (uchar**) &trg_fld-> + next_trg_field); $$= (Item *)trg_fld; } @@ -10152,7 +10145,7 @@ option_type_value: lex->option_type=OPT_SESSION; lex->var_list.empty(); lex->one_shot_set= 0; - lex->sphead->m_tmp_query= lip->tok_start; + lex->sphead->m_tmp_query= lip->get_tok_start(); } } ext_option_value @@ -10185,11 +10178,12 @@ option_type_value: lip->tok_end otherwise. */ if (yychar == YYEMPTY) - qbuff.length= lip->ptr - sp->m_tmp_query; + qbuff.length= lip->get_ptr() - sp->m_tmp_query; else - qbuff.length= lip->tok_end - sp->m_tmp_query; + qbuff.length= lip->get_tok_end() - sp->m_tmp_query; - if (!(qbuff.str= alloc_root(thd->mem_root, qbuff.length + 5))) + if (!(qbuff.str= (char*) alloc_root(thd->mem_root, + qbuff.length + 5))) MYSQL_YYABORT; strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query, @@ -10275,8 +10269,9 @@ sys_option_value: Let us add this item to list of all Item_trigger_field objects in trigger. */ - lex->trg_table_fields.link_in_list((byte *)trg_fld, - (byte **)&trg_fld->next_trg_field); + lex->trg_table_fields.link_in_list((uchar *)trg_fld, + (uchar **) &trg_fld-> + next_trg_field); lex->sphead->add_instr(sp_fld); } @@ -10553,7 +10548,7 @@ table_lock: lock_option: READ_SYM { $$=TL_READ_NO_INSERT; } - | WRITE_SYM { $$=YYTHD->update_lock_default; } + | WRITE_SYM { $$=TL_WRITE_DEFAULT; } | LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; } | READ_SYM LOCAL_SYM { $$= TL_READ; } ; @@ -10849,7 +10844,7 @@ grant_ident: { THD *thd= YYTHD; LEX *lex= thd->lex; - uint dummy; + size_t dummy; if (thd->copy_db_to(&lex->current_select->db, &dummy)) MYSQL_YYABORT; if (lex->grant == GLOBAL_ACLS) @@ -11238,7 +11233,8 @@ subselect_init: subselect_start: { LEX *lex=Lex; - if (!lex->expr_allows_subselect) + if (!lex->expr_allows_subselect || + lex->sql_command == (int)SQLCOM_PURGE) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -11366,7 +11362,7 @@ view_tail: if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING)) MYSQL_YYABORT; } - view_list_opt AS view_select view_check_option + view_list_opt AS view_select {} ; @@ -11391,40 +11387,32 @@ view_list: view_select: { + THD *thd= YYTHD; LEX *lex= Lex; + Lex_input_stream *lip= thd->m_lip; lex->parsing_options.allows_variable= FALSE; lex->parsing_options.allows_select_into= FALSE; lex->parsing_options.allows_select_procedure= FALSE; lex->parsing_options.allows_derived= FALSE; - } - view_select_aux + lex->create_view_select_start= lip->get_cpp_ptr(); + } + view_select_aux view_check_option { + THD *thd= YYTHD; LEX *lex= Lex; + Lex_input_stream *lip= thd->m_lip; lex->parsing_options.allows_variable= TRUE; lex->parsing_options.allows_select_into= TRUE; lex->parsing_options.allows_select_procedure= TRUE; lex->parsing_options.allows_derived= TRUE; + lex->create_view_select_end= lip->get_cpp_ptr(); } ; view_select_aux: - SELECT_SYM remember_name select_init2 - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - const char *stmt_beg= (lex->sphead ? - lex->sphead->m_tmp_query : thd->query); - lex->create_view_select_start= $2 - stmt_beg; - } - | '(' remember_name select_paren ')' union_opt - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - const char *stmt_beg= (lex->sphead ? - lex->sphead->m_tmp_query : thd->query); - lex->create_view_select_start= $2 - stmt_beg; - } - ; + SELECT_SYM select_init2 + | '(' select_paren ')' union_opt + ; view_check_option: /* empty */ @@ -11444,9 +11432,31 @@ view_check_option: **************************************************************************/ trigger_tail: - TRIGGER_SYM remember_name sp_name trg_action_time trg_event - ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM - { + TRIGGER_SYM + remember_name + sp_name + trg_action_time + trg_event + ON + remember_name /* $7 */ + { /* $8 */ + THD *thd= YYTHD; + LEX *lex= thd->lex; + Lex_input_stream *lip= thd->m_lip; + lex->raw_trg_on_table_name_begin= lip->get_tok_start(); + } + table_ident /* $9 */ + FOR_SYM + remember_name /* $11 */ + { /* $12 */ + THD *thd= YYTHD; + LEX *lex= thd->lex; + Lex_input_stream *lip= thd->m_lip; + lex->raw_trg_on_table_name_end= lip->get_tok_start(); + } + EACH_SYM + ROW_SYM + { /* $15 */ THD *thd= YYTHD; LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; @@ -11465,7 +11475,7 @@ trigger_tail: sp->init_sp_name(thd, $3); lex->stmt_definition_begin= $2; lex->ident.str= $7; - lex->ident.length= $10 - $7; + lex->ident.length= $11 - $7; sp->m_type= TYPE_ENUM_TRIGGER; lex->sphead= sp; @@ -11480,12 +11490,10 @@ trigger_tail: bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lip->ptr; - while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0])) - ++lex->sphead->m_body_begin; + lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_ptr()); } - sp_proc_stmt - { + sp_proc_stmt /* $16 */ + { /* $17 */ LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -11493,7 +11501,7 @@ trigger_tail: sp->init_strings(YYTHD, lex); /* Restore flag if it was cleared above */ - YYTHD->client_capabilities |= $<ulong_num>13; + YYTHD->client_capabilities |= $<ulong_num>15; sp->restore_thd_mem_root(YYTHD); if (sp->is_not_allowed_in_function("trigger")) @@ -11504,7 +11512,7 @@ trigger_tail: sp_proc_stmt alternatives are not saving/restoring LEX, so lex->query_tables can be wiped out. */ - if (!lex->select_lex.add_table_to_list(YYTHD, $8, + if (!lex->select_lex.add_table_to_list(YYTHD, $9, (LEX_STRING*) 0, TL_OPTION_UPDATING, TL_IGNORE)) @@ -11562,8 +11570,11 @@ sp_tail: THD *thd= YYTHD; LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; + const char* tmp_param_begin; - lex->sphead->m_param_begin= lip->tok_start+1; + tmp_param_begin= lip->get_cpp_tok_start(); + tmp_param_begin++; + lex->sphead->m_param_begin= tmp_param_begin; } sp_pdparam_list ')' @@ -11572,7 +11583,7 @@ sp_tail: LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; - lex->sphead->m_param_end= lip->tok_start; + lex->sphead->m_param_end= lip->get_cpp_tok_start(); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } sp_c_chistics @@ -11582,7 +11593,7 @@ sp_tail: Lex_input_stream *lip= thd->m_lip; lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lip->tok_start; + lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_tok_start()); } sp_proc_stmt { diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 078f62c6b2b..40507907120 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -94,7 +94,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) #endif /* defined(__alpha__) && defined(__GNUC__) */ -void print_stacktrace(gptr stack_bottom, ulong thread_stack) +void print_stacktrace(uchar* stack_bottom, ulong thread_stack) { uchar** fp; uint frame_count = 0, sigreturn_frame_count; @@ -129,11 +129,11 @@ terribly wrong...\n"); return; } - if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp) + if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp) { ulong tmp= min(0x10000,thread_stack); /* Assume that the stack starts at the previous even 65K */ - stack_bottom= (gptr) (((ulong) &fp + tmp) & + stack_bottom= (uchar*) (((ulong) &fp + tmp) & ~(ulong) 0xFFFF); fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp); } @@ -206,9 +206,11 @@ terribly wrong...\n"); fprintf(stderr, "Stack trace seems successful - bottom reached\n"); end: - fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/using-stack-trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ -stack trace is much more helpful in diagnosing the problem, so please do \n\ -resolve it\n"); + fprintf(stderr, + "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" + "and follow instructions on how to resolve the stack trace.\n" + "Resolved stack trace is much more helpful in diagnosing the\n" + "problem, so please do resolve it\n"); } #endif /* TARGET_OS_LINUX */ #endif /* HAVE_STACKTRACE */ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index 56b9877180a..1a0b80c88d3 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -28,7 +28,7 @@ extern char* heap_start; #define init_stacktrace() do { \ heap_start = (char*) &__bss_start; \ } while(0); -void print_stacktrace(gptr stack_bottom, ulong thread_stack); +void print_stacktrace(uchar* stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* TARGET_OS_LINUX */ diff --git a/sql/structs.h b/sql/structs.h index 139c07c90d6..da2339d27f8 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -28,8 +28,8 @@ typedef struct st_date_time_format { typedef struct st_keyfile_info { /* used with ha_info() */ - byte ref[MAX_REFLENGTH]; /* Pointer to current row */ - byte dupp_ref[MAX_REFLENGTH]; /* Pointer to dupp row */ + uchar ref[MAX_REFLENGTH]; /* Pointer to current row */ + uchar dupp_ref[MAX_REFLENGTH]; /* Pointer to dupp row */ uint ref_length; /* Length of ref (1-8) */ uint block_size; /* index block size */ File filenr; /* (uniq) filenr for table */ @@ -126,10 +126,10 @@ typedef struct st_read_record { /* Parameter to read_record */ uint cache_records; uint ref_length,struct_length,reclength,rec_cache_size,error_offset; uint index; - byte *ref_pos; /* pointer to form->refpos */ - byte *record; - byte *rec_buf; /* to read field values after filesort */ - byte *cache,*cache_pos,*cache_end,*read_positions; + uchar *ref_pos; /* pointer to form->refpos */ + uchar *record; + uchar *rec_buf; /* to read field values after filesort */ + uchar *cache,*cache_pos,*cache_end,*read_positions; IO_CACHE *io_cache; bool print_error, ignore_not_found_rows; } READ_RECORD; diff --git a/sql/table.cc b/sql/table.cc index 8eb01f06302..eab4d175fd8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -29,16 +29,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, File file); static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, char **names); -static uint find_field(Field **fields, byte *record, uint start, uint length); +static uint find_field(Field **fields, uchar *record, uint start, uint length); /* Get column name from column hash */ -static byte *get_field_name(Field **buff, uint *length, - my_bool not_used __attribute__((unused))) +static uchar *get_field_name(Field **buff, size_t *length, + my_bool not_used __attribute__((unused))) { *length= (uint) strlen((*buff)->field_name); - return (byte*) (*buff)->field_name; + return (uchar*) (*buff)->field_name; } @@ -343,10 +343,25 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) strxmov(path, share->normalized_path.str, reg_ext, NullS); if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) { - if (strchr(share->table_name.str, '@')) + /* + We don't try to open 5.0 unencoded name, if + - non-encoded name contains '@' signs, + because '@' can be misinterpreted. + It is not clear if '@' is escape character in 5.1, + or a normal character in 5.0. + + - non-encoded db or table name contain "#mysql50#" prefix. + This kind of tables must have been opened only by the + my_open() above. + */ + if (strchr(share->table_name.str, '@') || + !strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH) || + !strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH)) goto err_not_open; - /* Try unecoded 5.0 name */ + /* Try unencoded 5.0 name */ uint length; strxnmov(path, sizeof(path)-1, mysql_data_home, "/", share->db.str, "/", @@ -373,7 +388,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) } error= 4; - if (my_read(file,(byte*) head, 64, MYF(MY_NABP))) + if (my_read(file, head, 64, MYF(MY_NABP))) goto err; if (head[0] == (uchar) 254 && head[1] == 1) @@ -463,7 +478,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, uint extra_rec_buf_length; uint i,j; bool use_hash; - char *keynames, *record, *names, *comment_pos; + char *keynames, *names, *comment_pos; + uchar *record; uchar *disk_buff, *strpos, *null_flags, *null_pos; ulong pos, record_offset, *rec_per_key, rec_buff_length; handler *handler_file= 0; @@ -548,7 +564,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, /* Read keyinformation */ key_info_length= (uint) uint2korr(head+28); VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0))); - if (read_string(file,(gptr*) &disk_buff,key_info_length)) + if (read_string(file,(uchar**) &disk_buff,key_info_length)) goto err; /* purecov: inspected */ if (disk_buff[0] & 0x80) { @@ -647,19 +663,21 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if ((n_length= uint4korr(head+55))) { /* Read extra data segment */ - char *buff, *next_chunk, *buff_end; + uchar *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)))) + if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME)))) goto err; - if (my_pread(file, (byte*)buff, n_length, record_offset + share->reclength, + if (my_pread(file, buff, n_length, record_offset + share->reclength, MYF(MY_NABP))) { my_free(buff, MYF(0)); goto err; } share->connect_string.length= uint2korr(buff); - if (! (share->connect_string.str= strmake_root(&share->mem_root, - next_chunk + 2, share->connect_string.length))) + if (!(share->connect_string.str= strmake_root(&share->mem_root, + (char*) next_chunk + 2, + share->connect_string. + length))) { my_free(buff, MYF(0)); goto err; @@ -669,7 +687,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (next_chunk + 2 < buff_end) { uint str_db_type_length= uint2korr(next_chunk); - LEX_STRING name= { next_chunk + 2, str_db_type_length }; + LEX_STRING name; + name.str= (char*) next_chunk + 2; + name.length= str_db_type_length; + plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name); if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin)) { @@ -698,7 +719,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { LEX_STRING pname= { C_STRING_WITH_LEN( "partition" ) }; if (str_db_type_length == pname.length && - !strncmp(next_chunk + 2, pname.str, pname.length)) + !strncmp((char *) next_chunk + 2, pname.str, pname.length)) { /* Use partition handler @@ -720,9 +741,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { uint32 partition_info_len = uint4korr(next_chunk); #ifdef WITH_PARTITION_STORAGE_ENGINE - if ((share->partition_info_len= partition_info_len)) + if ((share->partition_info_buffer_size= + share->partition_info_len= partition_info_len)) { - if (!(share->partition_info= + if (!(share->partition_info= (char*) memdup_root(&share->mem_root, next_chunk + 4, partition_info_len + 1))) { @@ -774,8 +796,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, my_free(buff, MYF(0)); goto err; } - parser_name.str= next_chunk; - parser_name.length= strlen(next_chunk); + parser_name.str= (char*) next_chunk; + parser_name.length= strlen((char*) next_chunk); keyinfo->parser= my_plugin_lock_by_name(NULL, &parser_name, MYSQL_FTPARSER_PLUGIN); if (! keyinfo->parser) @@ -794,16 +816,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, extra_rec_buf_length= uint2korr(head+59); rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length); share->rec_buff_length= rec_buff_length; - if (!(record= (char *) alloc_root(&share->mem_root, - rec_buff_length))) + if (!(record= (uchar *) alloc_root(&share->mem_root, + rec_buff_length))) goto err; /* purecov: inspected */ - share->default_values= (byte *) record; - if (my_pread(file,(byte*) record, (uint) share->reclength, + share->default_values= record; + if (my_pread(file, record, (size_t) share->reclength, record_offset, MYF(MY_NABP))) goto err; /* purecov: inspected */ VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); - if (my_read(file,(byte*) head,288,MYF(MY_NABP))) + if (my_read(file, head,288,MYF(MY_NABP))) goto err; #ifdef HAVE_CRYPTED_FRM if (crypted) @@ -833,14 +855,14 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, (uint) ((share->fields+1)*sizeof(Field*)+ interval_count*sizeof(TYPELIB)+ (share->fields+interval_parts+ - keys+3)*sizeof(my_string)+ + keys+3)*sizeof(char *)+ (n_length+int_length+com_length))))) goto err; /* purecov: inspected */ share->field= field_ptr; read_length=(uint) (share->fields * field_pack_length + pos+ (uint) (n_length+int_length+com_length)); - if (read_string(file,(gptr*) &disk_buff,read_length)) + if (read_string(file,(uchar**) &disk_buff,read_length)) goto err; /* purecov: inspected */ #ifdef HAVE_CRYPTED_FRM if (crypted) @@ -896,7 +918,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, share->db_type()))) goto err; - record= (char*) share->default_values-1; /* Fieldstart = 1 */ + record= share->default_values-1; /* Fieldstart = 1 */ if (share->null_field_first) { null_flags= null_pos= (uchar*) record+1; @@ -1090,7 +1112,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (use_hash) (void) my_hash_insert(&share->name_hash, - (byte*) field_ptr); // never fail + (uchar*) field_ptr); // never fail } *field_ptr=0; // End marker @@ -1149,7 +1171,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, key_part->type= field->key_type(); if (field->null_ptr) { - key_part->null_offset=(uint) ((byte*) field->null_ptr - + key_part->null_offset=(uint) ((uchar*) field->null_ptr - share->default_values); key_part->null_bit= field->null_bit; key_part->store_length+=HA_KEY_NULL_LENGTH; @@ -1290,7 +1312,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, } else share->primary_key= MAX_KEY; - x_free((gptr) disk_buff); + x_free((uchar*) disk_buff); disk_buff=0; if (new_field_pack_flag <= 1) { @@ -1362,7 +1384,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, share->error= error; share->open_errno= my_errno; share->errarg= errarg; - x_free((gptr) disk_buff); + x_free((uchar*) disk_buff); delete crypted; delete handler_file; hash_free(&share->name_hash); @@ -1404,7 +1426,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, int error; uint records, i, bitmap_size; bool error_reported= FALSE; - byte *record, *bitmaps; + uchar *record, *bitmaps; Field **field_ptr; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, @@ -1439,7 +1461,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, if (prgflag & (READ_ALL+EXTRA_RECORD)) records++; - if (!(record= (byte*) alloc_root(&outparam->mem_root, + if (!(record= (uchar*) alloc_root(&outparam->mem_root, share->rec_buff_length * records))) goto err; /* purecov: inspected */ @@ -1479,7 +1501,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam->field= field_ptr; - record= (byte*) outparam->record[0]-1; /* Fieldstart = 1 */ + record= (uchar*) outparam->record[0]-1; /* Fieldstart = 1 */ if (share->null_field_first) outparam->null_flags= (uchar*) record+1; else @@ -1601,7 +1623,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, /* Allocate bitmaps */ bitmap_size= share->column_bitmap_size; - if (!(bitmaps= (byte*) alloc_root(&outparam->mem_root, bitmap_size*3))) + if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3))) goto err; bitmap_init(&outparam->def_read_set, (my_bitmap_map*) bitmaps, share->fields, FALSE); @@ -1768,7 +1790,7 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) DBUG_ENTER("get_form_pos"); names=uint2korr(head+8); - a_length=(names+2)*sizeof(my_string); /* Room for two extra */ + a_length=(names+2)*sizeof(char *); /* Room for two extra */ if (!save_names) a_length=0; @@ -1779,12 +1801,12 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) { length=uint2korr(head+4); VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0))); - if (!(buf= (uchar*) my_malloc((uint) length+a_length+names*4, + if (!(buf= (uchar*) my_malloc((size_t) length+a_length+names*4, MYF(MY_WME))) || - my_read(file,(byte*) buf+a_length,(uint) (length+names*4), + my_read(file, buf+a_length, (size_t) (length+names*4), MYF(MY_NABP))) { /* purecov: inspected */ - x_free((gptr) buf); /* purecov: inspected */ + x_free((uchar*) buf); /* purecov: inspected */ DBUG_RETURN(0L); /* purecov: inspected */ } pos= buf+a_length+length; @@ -1793,7 +1815,7 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) if (! save_names) { if (names) - my_free((gptr) buf,MYF(0)); + my_free((uchar*) buf,MYF(0)); } else if (!names) bzero((char*) save_names,sizeof(save_names)); @@ -1807,19 +1829,24 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) } - /* Read string from a file with malloc */ +/* + Read string from a file with malloc + + NOTES: + We add an \0 at end of the read string to make reading of C strings easier +*/ -int read_string(File file, gptr *to, uint length) +int read_string(File file, uchar**to, size_t length) { DBUG_ENTER("read_string"); - x_free((gptr) *to); - if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) || - my_read(file,(byte*) *to,length,MYF(MY_NABP))) + x_free(*to); + if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) || + my_read(file, *to, length,MYF(MY_NABP))) { - x_free((gptr) *to); /* purecov: inspected */ - *to= 0; /* purecov: inspected */ - DBUG_RETURN(1); /* purecov: inspected */ + x_free(*to); /* purecov: inspected */ + *to= 0; /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ } *((char*) *to+length)= '\0'; DBUG_RETURN (0); @@ -1833,7 +1860,7 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, { uint i,bufflength,maxlength,n_length,length,names; ulong endpos,newpos; - char buff[IO_SIZE]; + uchar buff[IO_SIZE]; uchar *pos; DBUG_ENTER("make_new_entry"); @@ -1853,17 +1880,17 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, while (endpos > maxlength) { VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0))); - if (my_read(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) + if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET, MYF(0))); - if ((my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))) + if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME)))) DBUG_RETURN(0); endpos-=bufflength; bufflength=IO_SIZE; } bzero(buff,IO_SIZE); /* Null new block */ VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0))); - if (my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) + if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); maxlength+=IO_SIZE; /* Fix old ref */ int2store(fileinfo+6,maxlength); @@ -1878,15 +1905,15 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, if (n_length == 1 ) { /* First name */ length++; - VOID(strxmov(buff,"/",newname,"/",NullS)); + VOID(strxmov((char*) buff,"/",newname,"/",NullS)); } else - VOID(strxmov(buff,newname,"/",NullS)); /* purecov: inspected */ + VOID(strxmov((char*) buff,newname,"/",NullS)); /* purecov: inspected */ VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0))); - if (my_write(file,(byte*) buff,(uint) length+1,MYF(MY_NABP+MY_WME)) || - (names && my_write(file,(byte*) (*formnames->type_names+n_length-1), + if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) || + (names && my_write(file,(uchar*) (*formnames->type_names+n_length-1), names*4, MYF(MY_NABP+MY_WME))) || - my_write(file,(byte*) fileinfo+10,(uint) 4,MYF(MY_NABP+MY_WME))) + my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); /* purecov: inspected */ int2store(fileinfo+8,names+1); @@ -2046,7 +2073,7 @@ TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings) # field number +1 */ -static uint find_field(Field **fields, byte *record, uint start, uint length) +static uint find_field(Field **fields, uchar *record, uint start, uint length) { Field **field; uint i, pos; @@ -2159,7 +2186,7 @@ File create_frm(THD *thd, const char *name, const char *db, { register File file; ulong length; - char fill[IO_SIZE]; + uchar fill[IO_SIZE]; int create_flags= O_RDWR | O_TRUNC; if (create_info->options & HA_LEX_CREATE_TMP_TABLE) @@ -2222,7 +2249,7 @@ File create_frm(THD *thd, const char *name, const char *db, bzero(fill,IO_SIZE); for (; length > IO_SIZE ; length-= IO_SIZE) { - if (my_write(file,(byte*) fill,IO_SIZE,MYF(MY_WME | MY_NABP))) + if (my_write(file,fill, IO_SIZE, MYF(MY_WME | MY_NABP))) { VOID(my_close(file,MYF(0))); VOID(my_delete(name,MYF(0))); @@ -2333,7 +2360,7 @@ char *get_field(MEM_ROOT *mem, Field *field) given a buffer with a key value, and a map of keyparts that are present in this value, returns the length of the value */ -uint calculate_key_len(TABLE *table, uint key, const byte *buf, +uint calculate_key_len(TABLE *table, uint key, const uchar *buf, key_part_map keypart_map) { /* works only with key prefixes */ @@ -2778,7 +2805,7 @@ bool st_table_list::setup_underlying(THD *thd) List_iterator_fast<Item> it(select->item_list); uint field_count= 0; - if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count)) + if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*) &field_count)) { DBUG_RETURN(TRUE); } @@ -2903,6 +2930,47 @@ bool st_table_list::prep_where(THD *thd, Item **conds, /* + Merge ON expressions for a view + + SYNOPSIS + merge_on_conds() + thd thread handle + table table for the VIEW + is_cascaded TRUE <=> merge ON expressions from underlying views + + DESCRIPTION + This function returns the result of ANDing the ON expressions + of the given view and all underlying views. The ON expressions + of the underlying views are added only if is_cascaded is TRUE. + + RETURN + Pointer to the built expression if there is any. + Otherwise and in the case of a failure NULL is returned. +*/ + +static Item * +merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded) +{ + DBUG_ENTER("merge_on_conds"); + + Item *cond= NULL; + DBUG_PRINT("info", ("alias: %s", table->alias)); + if (table->on_expr) + cond= table->on_expr->copy_andor_structure(thd); + if (!table->nested_join) + DBUG_RETURN(cond); + List_iterator<TABLE_LIST> li(table->nested_join->join_list); + while (TABLE_LIST *tbl= li++) + { + if (tbl->view && !is_cascaded) + continue; + cond= and_conds(cond, merge_on_conds(thd, tbl, is_cascaded)); + } + DBUG_RETURN(cond); +} + + +/* Prepare check option expression of table SYNOPSIS @@ -2918,8 +2986,8 @@ bool st_table_list::prep_where(THD *thd, Item **conds, VIEW_CHECK_LOCAL option. NOTE - This method build check options for every call - (usual execution or every SP/PS call) + This method builds check option condition to use it later on + every call (usual execution or every SP/PS call). This method have to be called after WHERE preparation (st_table_list::prep_where) @@ -2931,38 +2999,42 @@ bool st_table_list::prep_where(THD *thd, Item **conds, bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) { DBUG_ENTER("st_table_list::prep_check_option"); + bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED; for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { /* see comment of check_opt_type parameter */ - if (tbl->view && - tbl->prep_check_option(thd, - ((check_opt_type == VIEW_CHECK_CASCADED) ? - VIEW_CHECK_CASCADED : - VIEW_CHECK_NONE))) - { + if (tbl->view && tbl->prep_check_option(thd, (is_cascaded ? + VIEW_CHECK_CASCADED : + VIEW_CHECK_NONE))) DBUG_RETURN(TRUE); - } } - if (check_opt_type) + if (check_opt_type && !check_option_processed) { - Item *item= 0; + Query_arena *arena= thd->stmt_arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test + if (where) { DBUG_ASSERT(where->fixed); - item= where->copy_andor_structure(thd); + check_option= where->copy_andor_structure(thd); } - if (check_opt_type == VIEW_CHECK_CASCADED) + if (is_cascaded) { for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { if (tbl->check_option) - item= and_conds(item, tbl->check_option); + check_option= and_conds(check_option, tbl->check_option); } } - if (item) - thd->change_item_tree(&check_option, item); + check_option= and_conds(check_option, + merge_on_conds(thd, this, is_cascaded)); + + if (arena) + thd->restore_active_arena(arena, &backup); + check_option_processed= TRUE; + } if (check_option) @@ -3067,7 +3139,7 @@ void st_table_list::cleanup_items() check CHECK OPTION condition SYNOPSIS - check_option() + st_table_list::view_check_option() ignore_failure ignore check option fail RETURN @@ -3153,7 +3225,7 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root) if (table) { if (!table->insert_values && - !(table->insert_values= (byte *)alloc_root(mem_root, + !(table->insert_values= (uchar *)alloc_root(mem_root, table->s->rec_buff_length))) return TRUE; } @@ -4406,6 +4478,24 @@ bool st_table_list::process_index_hints(TABLE *table) return 0; } + +size_t max_row_length(TABLE *table, const uchar *data) +{ + TABLE_SHARE *table_s= table->s; + size_t length= table_s->reclength + 2 * table_s->fields; + uint *const beg= table_s->blob_field; + uint *const end= beg + table_s->blob_fields; + + for (uint *ptr= beg ; ptr != end ; ++ptr) + { + Field_blob* const blob= (Field_blob*) table->field[*ptr]; + length+= blob->get_length((const uchar*) + (data + blob->offset(table->record[0]))) + + HA_KEY_BLOB_LENGTH; + } + return length; +} + /***************************************************************************** ** Instansiate templates *****************************************************************************/ diff --git a/sql/table.h b/sql/table.h index 99fbf57bb52..90c07979512 100644 --- a/sql/table.h +++ b/sql/table.h @@ -73,16 +73,16 @@ enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; typedef struct st_filesort_info { - IO_CACHE *io_cache; /* If sorted through filebyte */ - uchar **sort_keys; /* Buffer for sorting keys */ - byte *buffpek; /* Buffer for buffpek structures */ - uint buffpek_len; /* Max number of buffpeks in the buffer */ - byte *addon_buf; /* Pointer to a buffer if sorted with fields */ - uint addon_length; /* Length of the buffer */ + IO_CACHE *io_cache; /* If sorted through filesort */ + uchar **sort_keys; /* Buffer for sorting keys */ + uchar *buffpek; /* Buffer for buffpek structures */ + uint buffpek_len; /* Max number of buffpeks in the buffer */ + uchar *addon_buf; /* Pointer to a buffer if sorted with fields */ + size_t addon_length; /* Length of the buffer */ struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ - void (*unpack)(struct st_sort_addon_field *, byte *); /* To unpack back */ - byte *record_pointers; /* If sorted in memory */ - ha_rows found_records; /* How many records in sort */ + void (*unpack)(struct st_sort_addon_field *, uchar *); /* To unpack back */ + uchar *record_pointers; /* If sorted in memory */ + ha_rows found_records; /* How many records in sort */ } FILESORT_INFO; @@ -137,7 +137,7 @@ typedef struct st_table_share KEY *key_info; /* data of keys in database */ uint *blob_field; /* Index to blobs in Field arrray*/ - byte *default_values; /* row with default values */ + uchar *default_values; /* row with default values */ LEX_STRING comment; /* Comment about table */ CHARSET_INFO *table_charset; /* Default charset of string fields */ @@ -243,6 +243,7 @@ typedef struct st_table_share bool auto_partitioned; const char *partition_info; uint partition_info_len; + uint partition_info_buffer_size; const char *part_state; uint part_state_len; handlerton *default_part_db_type; @@ -328,10 +329,10 @@ struct st_table { THD *in_use; /* Which thread uses this */ Field **field; /* Pointer to fields */ - byte *record[2]; /* Pointer to records */ - byte *write_row_record; /* Used as optimisation in + uchar *record[2]; /* Pointer to records */ + uchar *write_row_record; /* Used as optimisation in THD::write_row */ - byte *insert_values; /* used by INSERT ... UPDATE */ + uchar *insert_values; /* used by INSERT ... UPDATE */ /* Map of keys that can be used to retrieve all data from this table needed by the query without reading the row. @@ -429,12 +430,14 @@ struct st_table { /* If true, the current table row is considered to have all columns set to NULL, including columns declared as "not null" (see maybe_null). + */ + my_bool null_row; - TODO: Each of these flags take up 8 bits. They can just as easily + /* + TODO: Each of the following flags take up 8 bits. They can just as easily be put into one single unsigned long and instead of taking up 18 bytes, it would take up 4. */ - my_bool null_row; my_bool force_index; my_bool distinct,const_table,no_rows; my_bool key_read, no_keyread; @@ -887,8 +890,8 @@ typedef struct st_table_list thr_lock_type lock_type; uint outer_join; /* Which join type */ uint shared; /* Used in multi-upd */ - uint db_length; - uint32 table_name_length; + size_t db_length; + size_t table_name_length; bool updatable; /* VIEW/TABLE can be updated now */ bool straight; /* optimize with prev table */ bool updating; /* for replicate-do/ignore table */ @@ -909,6 +912,8 @@ typedef struct st_table_list bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */ /* view where processed */ bool where_processed; + /* TRUE <=> VIEW CHECK OPTION expression has been processed */ + bool check_option_processed; /* FRMTYPE_ERROR if any type is acceptable */ enum frm_type_enum required_type; handlerton *db_type; /* table_type for handler */ @@ -1192,3 +1197,6 @@ static inline void dbug_tmp_restore_column_map(MY_BITMAP *bitmap, tmp_restore_column_map(bitmap, old); #endif } + +size_t max_row_length(TABLE *table, const uchar *data); + diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index 392db9224c3..ddf35002880 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -35,26 +35,25 @@ void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc) } -gptr sql_alloc(uint Size) +void *sql_alloc(size_t Size) { MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC); - char *ptr= (char*) alloc_root(root,Size); - return ptr; + return alloc_root(root,Size); } -gptr sql_calloc(uint size) +void *sql_calloc(size_t size) { - gptr ptr; + void *ptr; if ((ptr=sql_alloc(size))) - bzero((char*) ptr,size); + bzero(ptr,size); return ptr; } char *sql_strdup(const char *str) { - uint len=(uint) strlen(str)+1; + size_t len= strlen(str)+1; char *pos; if ((pos= (char*) sql_alloc(len))) memcpy(pos,str,len); @@ -62,7 +61,7 @@ char *sql_strdup(const char *str) } -char *sql_strmake(const char *str,uint len) +char *sql_strmake(const char *str, size_t len) { char *pos; if ((pos= (char*) sql_alloc(len+1))) @@ -74,10 +73,10 @@ char *sql_strmake(const char *str,uint len) } -gptr sql_memdup(const void *ptr,uint len) +void* sql_memdup(const void *ptr, size_t len) { - char *pos; - if ((pos= (char*) sql_alloc(len))) + void *pos; + if ((pos= sql_alloc(len))) memcpy(pos,ptr,len); return pos; } @@ -87,17 +86,17 @@ void sql_element_free(void *ptr __attribute__((unused))) -char *sql_strmake_with_convert(const char *str, uint32 arg_length, +char *sql_strmake_with_convert(const char *str, size_t arg_length, CHARSET_INFO *from_cs, - uint32 max_res_length, - CHARSET_INFO *to_cs, uint32 *result_length) + size_t max_res_length, + CHARSET_INFO *to_cs, size_t *result_length) { char *pos; - uint32 new_length= to_cs->mbmaxlen*arg_length; + size_t new_length= to_cs->mbmaxlen*arg_length; max_res_length--; // Reserve place for end null set_if_smaller(new_length, max_res_length); - if (!(pos= sql_alloc(new_length+1))) + if (!(pos= (char*) sql_alloc(new_length+1))) return pos; // Error if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) diff --git a/sql/tzfile.h b/sql/tzfile.h index 1a57c0c5f69..1ff82d62329 100644 --- a/sql/tzfile.h +++ b/sql/tzfile.h @@ -34,14 +34,14 @@ #define TZ_MAGIC "TZif" struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_reserved[16]; /* reserved for future use */ - char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ + uchar tzh_magic[4]; /* TZ_MAGIC */ + uchar tzh_reserved[16]; /* reserved for future use */ + uchar tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ + uchar tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + uchar tzh_leapcnt[4]; /* coded number of leap seconds */ + uchar tzh_timecnt[4]; /* coded number of transition times */ + uchar tzh_typecnt[4]; /* coded number of local time types */ + uchar tzh_charcnt[4]; /* coded number of abbr. chars */ }; /* diff --git a/sql/tztime.cc b/sql/tztime.cc index 08b93cfd203..0c717dd2ece 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -153,7 +153,7 @@ static my_bool prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage); static my_bool tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) { - char *p; + uchar *p; int read_from_file; uint i; FILE *file; @@ -164,8 +164,8 @@ tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) union { struct tzhead tzhead; - char buf[sizeof(struct tzhead) + sizeof(my_time_t) * TZ_MAX_TIMES + - TZ_MAX_TIMES + sizeof(TRAN_TYPE_INFO) * TZ_MAX_TYPES + + uchar buf[sizeof(struct tzhead) + sizeof(my_time_t) * TZ_MAX_TIMES + + TZ_MAX_TIMES + sizeof(TRAN_TYPE_INFO) * TZ_MAX_TYPES + #ifdef ABBR_ARE_USED max(TZ_MAX_CHARS + 1, (2 * (MY_TZNAME_MAX + 1))) + #endif @@ -189,7 +189,7 @@ tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) sp->timecnt= int4net(u.tzhead.tzh_timecnt); sp->typecnt= int4net(u.tzhead.tzh_typecnt); sp->charcnt= int4net(u.tzhead.tzh_charcnt); - p= u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; + p= u.tzhead.tzh_charcnt + sizeof(u.tzhead.tzh_charcnt); if (sp->leapcnt > TZ_MAX_LEAPS || sp->typecnt == 0 || sp->typecnt > TZ_MAX_TYPES || sp->timecnt > TZ_MAX_TIMES || @@ -1489,18 +1489,21 @@ public: they should obey C calling conventions. */ -extern "C" byte* my_tz_names_get_key(Tz_names_entry *entry, uint *length, - my_bool not_used __attribute__((unused))) +extern "C" uchar * +my_tz_names_get_key(Tz_names_entry *entry, size_t *length, + my_bool not_used __attribute__((unused))) { *length= entry->name.length(); - return (byte*) entry->name.ptr(); + return (uchar*) entry->name.ptr(); } -extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length, - my_bool not_used __attribute__((unused))) +extern "C" uchar * +my_offset_tzs_get_key(Time_zone_offset *entry, + size_t *length, + my_bool not_used __attribute__((unused))) { *length= sizeof(long); - return (byte*) &entry->offset; + return (uchar*) &entry->offset; } @@ -1586,7 +1589,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) /* Init all memory structures that require explicit destruction */ if (hash_init(&tz_names, &my_charset_latin1, 20, - 0, 0, (hash_get_key)my_tz_names_get_key, 0, 0)) + 0, 0, (hash_get_key) my_tz_names_get_key, 0, 0)) { sql_print_error("Fatal error: OOM while initializing time zones"); goto end; @@ -1610,7 +1613,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) } tmp_tzname->name.set(STRING_WITH_LEN("SYSTEM"), &my_charset_latin1); tmp_tzname->tz= my_tz_SYSTEM; - if (my_hash_insert(&tz_names, (const byte *)tmp_tzname)) + if (my_hash_insert(&tz_names, (const uchar *)tmp_tzname)) { sql_print_error("Fatal error: OOM while initializing time zones"); goto end_with_cleanup; @@ -1832,8 +1835,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) DBUG_ENTER("tz_load_from_open_tables"); /* Prepare tz_info for loading also let us make copy of time zone name */ - if (!(alloc_buff= alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) + - tz_name->length() + 1))) + if (!(alloc_buff= (char*) alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) + + tz_name->length() + 1))) { sql_print_error("Out of memory while loading time zone description"); return 0; @@ -1862,7 +1865,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) */ (void)table->file->ha_index_init(0, 1); - if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, + if (table->file->index_read(table->record[0], table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { #ifdef EXTRA_DEBUG @@ -1889,7 +1892,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, + if (table->file->index_read(table->record[0], table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { sql_print_error("Can't find description of time zone '%u'", tzid); @@ -1916,7 +1919,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, + res= table->file->index_read(table->record[0], table->field[0]->ptr, (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { @@ -1965,7 +1968,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tz_info->typecnt= ttid + 1; res= table->file->index_next_same(table->record[0], - (byte*)table->field[0]->ptr, 4); + table->field[0]->ptr, 4); } if (res != HA_ERR_END_OF_FILE) @@ -1987,7 +1990,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, + res= table->file->index_read(table->record[0], table->field[0]->ptr, (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { @@ -2018,7 +2021,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tzid, (ulong) ttime, ttid)); res= table->file->index_next_same(table->record[0], - (byte*)table->field[0]->ptr, 4); + table->field[0]->ptr, 4); } /* @@ -2038,21 +2041,21 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) /* Now we will allocate memory and init TIME_ZONE_INFO structure. */ - if (!(alloc_buff= alloc_root(&tz_storage, - ALIGN_SIZE(sizeof(my_time_t) * - tz_info->timecnt) + - ALIGN_SIZE(tz_info->timecnt) + + if (!(alloc_buff= (char*) alloc_root(&tz_storage, + ALIGN_SIZE(sizeof(my_time_t) * + tz_info->timecnt) + + ALIGN_SIZE(tz_info->timecnt) + #ifdef ABBR_ARE_USED - ALIGN_SIZE(tz_info->charcnt) + + ALIGN_SIZE(tz_info->charcnt) + #endif - sizeof(TRAN_TYPE_INFO) * tz_info->typecnt))) + sizeof(TRAN_TYPE_INFO) * + tz_info->typecnt))) { sql_print_error("Out of memory while loading time zone description"); goto end; } - - tz_info->ats= (my_time_t *)alloc_buff; + tz_info->ats= (my_time_t *) alloc_buff; memcpy(tz_info->ats, ats, tz_info->timecnt * sizeof(my_time_t)); alloc_buff+= ALIGN_SIZE(sizeof(my_time_t) * tz_info->timecnt); tz_info->types= (uchar *)alloc_buff; @@ -2087,7 +2090,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) &(tmp_tzname->name))) || (tmp_tzname->name.set(tz_name_buff, tz_name->length(), &my_charset_latin1), - my_hash_insert(&tz_names, (const byte *)tmp_tzname))) + my_hash_insert(&tz_names, (const uchar *)tmp_tzname))) { sql_print_error("Out of memory while loading time zone"); goto end; @@ -2244,13 +2247,13 @@ my_tz_find(THD *thd, const String *name) { if (!(result_tz= (Time_zone_offset *)hash_search(&offset_tzs, - (const byte *)&offset, + (const uchar *)&offset, sizeof(long)))) { DBUG_PRINT("info", ("Creating new Time_zone_offset object")); if (!(result_tz= new (&tz_storage) Time_zone_offset(offset)) || - my_hash_insert(&offset_tzs, (const byte *) result_tz)) + my_hash_insert(&offset_tzs, (const uchar *) result_tz)) { result_tz= 0; sql_print_error("Fatal error: Out of memory " @@ -2262,7 +2265,7 @@ my_tz_find(THD *thd, const String *name) { result_tz= 0; if ((tmp_tzname= (Tz_names_entry *)hash_search(&tz_names, - (const byte *)name->ptr(), + (const uchar *)name->ptr(), name->length()))) result_tz= tmp_tzname->tz; else if (time_zone_tables_exist) diff --git a/sql/udf_example.c b/sql/udf_example.c index d37c6505ced..b603464568e 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -130,7 +130,8 @@ typedef long long longlong; #include <m_string.h> /* To get strmov() */ #else /* when compiled as standalone */ -#define strmov(a,b) strcpy(a,b) +#include <string.h> +#define strmov(a,b) stpcpy(a,b) #define bzero(a,b) memset(a,0,b) #define memcpy_fixed(a,b,c) memcpy(a,b,c) #endif diff --git a/sql/uniques.cc b/sql/uniques.cc index 9eb827f62a3..7a05ceaddfc 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -34,7 +34,7 @@ #include "sql_sort.h" -int unique_write_to_file(gptr key, element_count count, Unique *unique) +int unique_write_to_file(uchar* key, element_count count, Unique *unique) { /* Use unique->size (size of element stored in the tree) and not @@ -42,11 +42,10 @@ int unique_write_to_file(gptr key, element_count count, Unique *unique) when tree implementation chooses to store pointer to key in TREE_ELEMENT (instead of storing the element itself there) */ - return my_b_write(&unique->file, (byte*) key, - unique->size) ? 1 : 0; + return my_b_write(&unique->file, key, unique->size) ? 1 : 0; } -int unique_write_to_ptrs(gptr key, element_count count, Unique *unique) +int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique) { memcpy(unique->record_pointers, key, unique->size); unique->record_pointers+=unique->size; @@ -330,7 +329,7 @@ bool Unique::flush() if (tree_walk(&tree, (tree_walk_action) unique_write_to_file, (void*) this, left_root_right) || - insert_dynamic(&file_ptrs, (gptr) &file_ptr)) + insert_dynamic(&file_ptrs, (uchar*) &file_ptr)) return 1; delete_tree(&tree); return 0; @@ -374,11 +373,11 @@ struct BUFFPEK_COMPARE_CONTEXT C_MODE_START -static int buffpek_compare(void *arg, byte *key_ptr1, byte *key_ptr2) +static int buffpek_compare(void *arg, uchar *key_ptr1, uchar *key_ptr2) { BUFFPEK_COMPARE_CONTEXT *ctx= (BUFFPEK_COMPARE_CONTEXT *) arg; return ctx->key_compare(ctx->key_compare_arg, - *((byte **) key_ptr1), *((byte **)key_ptr2)); + *((uchar **) key_ptr1), *((uchar **)key_ptr2)); } C_MODE_END @@ -455,7 +454,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, if (bytes_read == (uint) (-1)) goto end; DBUG_ASSERT(bytes_read); - queue_insert(&queue, (byte *) top); + queue_insert(&queue, (uchar *) top); } top= (BUFFPEK *) queue_top(&queue); while (queue.elements > 1) @@ -586,7 +585,7 @@ bool Unique::get(TABLE *table) if (my_b_tell(&file) == 0) { /* Whole tree is in memory; Don't use disk if you don't need to */ - if ((record_pointers=table->sort.record_pointers= (byte*) + if ((record_pointers=table->sort.record_pointers= (uchar*) my_malloc(size * tree.elements_in_tree, MYF(0)))) { (void) tree_walk(&tree, (tree_walk_action) unique_write_to_ptrs, @@ -641,7 +640,7 @@ bool Unique::get(TABLE *table) goto err; error=0; err: - x_free((gptr) sort_buffer); + x_free(sort_buffer); if (flush_io_cache(outfile)) error=1; diff --git a/sql/unireg.cc b/sql/unireg.cc index a69a9be6a43..57847bc70c6 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -29,21 +29,21 @@ #define FCOMP 17 /* Bytes for a packed field */ -static uchar * pack_screens(List<create_field> &create_fields, +static uchar * pack_screens(List<Create_field> &create_fields, uint *info_length, uint *screens, bool small_file); static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info, ulong data_offset); static bool pack_header(uchar *forminfo,enum legacy_db_type table_type, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint info_length, uint screens, uint table_options, ulong data_offset, handler *file); -static uint get_interval_id(uint *int_count,List<create_field> &create_fields, - create_field *last_field); -static bool pack_fields(File file, List<create_field> &create_fields, +static uint get_interval_id(uint *int_count,List<Create_field> &create_fields, + Create_field *last_field); +static bool pack_fields(File file, List<Create_field> &create_fields, ulong data_offset); static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type, uint table_options, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint reclength, ulong data_offset, handler *handler); @@ -70,7 +70,7 @@ static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type, bool mysql_create_frm(THD *thd, const char *file_name, const char *db, const char *table, HA_CREATE_INFO *create_info, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint keys, KEY *key_info, handler *db_file) { @@ -104,7 +104,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, screens, create_info->table_options, data_offset, db_file)) { - my_free((gptr) screen_buff,MYF(0)); + my_free(screen_buff, MYF(0)); if (thd->net.last_errno != ER_TOO_MANY_FIELDS) DBUG_RETURN(1); @@ -116,7 +116,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, create_fields,info_length, screens, create_info->table_options, data_offset, db_file)) { - my_free((gptr) screen_buff,MYF(0)); + my_free(screen_buff, MYF(0)); DBUG_RETURN(1); } } @@ -152,7 +152,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo, create_info, keys)) < 0) { - my_free((gptr) screen_buff,MYF(0)); + my_free(screen_buff, MYF(0)); DBUG_RETURN(1); } @@ -200,8 +200,8 @@ bool mysql_create_frm(THD *thd, const char *file_name, #endif int2store(fileinfo+59,db_file->extra_rec_buf_length()); - if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) || - my_pwrite(file,(byte*) keybuff,key_info_length, + if (my_pwrite(file, fileinfo, 64, 0L, MYF_RW) || + my_pwrite(file, keybuff, key_info_length, (ulong) uint2korr(fileinfo+6),MYF_RW)) goto err; VOID(my_seek(file, @@ -213,14 +213,14 @@ bool mysql_create_frm(THD *thd, const char *file_name, goto err; int2store(buff, create_info->connect_string.length); - if (my_write(file, (const byte*)buff, 2, MYF(MY_NABP)) || - my_write(file, (const byte*)create_info->connect_string.str, + if (my_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || + my_write(file, (const uchar*)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, 2, MYF(MY_NABP)) || - my_write(file, (const byte*)str_db_type.str, + if (my_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || + my_write(file, (const uchar*)str_db_type.str, str_db_type.length, MYF(MY_NABP))) goto err; @@ -229,32 +229,32 @@ bool mysql_create_frm(THD *thd, const char *file_name, { char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0; 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, + if (my_write(file, (const uchar*)buff, 4, MYF_RW) || + my_write(file, (const uchar*)part_info->part_info_string, part_info->part_info_len + 1, MYF_RW) || - my_write(file, (const byte*)&auto_partitioned, 1, MYF_RW)) + my_write(file, (const uchar*)&auto_partitioned, 1, MYF_RW)) goto err; } else #endif { - bzero(buff, 6); - if (my_write(file, (byte*) buff, 6, MYF_RW)) + bzero((uchar*) buff, 6); + if (my_write(file, (uchar*) buff, 6, 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, + if (my_write(file, (const uchar*)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) || + if (my_write(file, forminfo, 288, MYF_RW) || + my_write(file, screen_buff, info_length, MYF_RW) || pack_fields(file, create_fields, data_offset)) goto err; @@ -267,7 +267,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, goto err; uint read_length=uint2korr(forminfo)-256; VOID(my_seek(file,filepos+256,MY_SEEK_SET,MYF(0))); - if (read_string(file,(gptr*) &disk_buff,read_length)) + if (read_string(file,(uchar**) &disk_buff,read_length)) goto err; crypted->encode(disk_buff,read_length); delete crypted; @@ -280,8 +280,8 @@ bool mysql_create_frm(THD *thd, const char *file_name, } #endif - my_free((gptr) screen_buff,MYF(0)); - my_free((gptr) keybuff, MYF(0)); + my_free(screen_buff,MYF(0)); + my_free(keybuff, MYF(0)); if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) && my_sync(file, MYF(MY_WME))) @@ -294,8 +294,8 @@ bool mysql_create_frm(THD *thd, const char *file_name, Restore all UCS2 intervals. HEX representation of them is not needed anymore. */ - List_iterator<create_field> it(create_fields); - create_field *field; + List_iterator<Create_field> it(create_fields); + Create_field *field; while ((field=it++)) { if (field->save_interval) @@ -308,8 +308,8 @@ bool mysql_create_frm(THD *thd, const char *file_name, DBUG_RETURN(0); err: - my_free((gptr) screen_buff,MYF(0)); - my_free((gptr) keybuff, MYF(0)); + my_free(screen_buff, MYF(0)); + my_free(keybuff, MYF(0)); err2: VOID(my_close(file,MYF(MY_WME))); err3: @@ -341,7 +341,7 @@ err3: int rea_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint keys, KEY *key_info, handler *file) { DBUG_ENTER("rea_create_table"); @@ -371,7 +371,7 @@ err_handler: /* Pack screens to a screen for save in a form-file */ -static uchar *pack_screens(List<create_field> &create_fields, +static uchar *pack_screens(List<Create_field> &create_fields, uint *info_length, uint *screens, bool small_file) { @@ -380,7 +380,7 @@ static uchar *pack_screens(List<create_field> &create_fields, uint length,cols; uchar *info,*pos,*start_screen; uint fields=create_fields.elements; - List_iterator<create_field> it(create_fields); + List_iterator<Create_field> it(create_fields); DBUG_ENTER("pack_screens"); start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row; @@ -388,7 +388,7 @@ static uchar *pack_screens(List<create_field> &create_fields, *screens=(fields-1)/fields_on_screen+1; length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4); - create_field *field; + Create_field *field; while ((field=it++)) length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2; @@ -401,7 +401,7 @@ static uchar *pack_screens(List<create_field> &create_fields, it.rewind(); for (i=0 ; i < fields ; i++) { - create_field *cfield=it++; + Create_field *cfield=it++; if (row++ == end_row) { if (i) @@ -417,7 +417,7 @@ static uchar *pack_screens(List<create_field> &create_fields, pos[0]= (uchar) start_row-2; /* Header string */ pos[1]= (uchar) (cols >> 2); pos[2]= (uchar) (cols >> 1) +1; - strfill((my_string) pos+3,(uint) (cols >> 1),' '); + strfill((char *) pos+3,(uint) (cols >> 1),' '); pos+=(cols >> 1)+4; } length=(uint) strlen(cfield->field_name); @@ -521,7 +521,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, /* Make formheader */ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint info_length, uint screens, uint table_options, ulong data_offset, handler *file) { @@ -544,8 +544,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, /* Check fields */ - List_iterator<create_field> it(create_fields); - create_field *field; + List_iterator<Create_field> it(create_fields); + Create_field *field; while ((field=it++)) { uint tmp_len= system_charset_info->cset->charpos(system_charset_info, @@ -626,7 +626,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, length= field->save_interval->type_lengths[pos]; hex_length= length * 2; field->interval->type_lengths[pos]= hex_length; - field->interval->type_names[pos]= dst= sql_alloc(hex_length + 1); + field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length + + 1); octet2hex(dst, src, length); } } @@ -686,11 +687,11 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, /* get each unique interval each own id */ -static uint get_interval_id(uint *int_count,List<create_field> &create_fields, - create_field *last_field) +static uint get_interval_id(uint *int_count,List<Create_field> &create_fields, + Create_field *last_field) { - List_iterator<create_field> it(create_fields); - create_field *field; + List_iterator<Create_field> it(create_fields); + Create_field *field; TYPELIB *interval=last_field->interval; while ((field=it++) != last_field) @@ -714,18 +715,18 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields, /* Save fields, fieldnames and intervals */ -static bool pack_fields(File file, List<create_field> &create_fields, +static bool pack_fields(File file, List<Create_field> &create_fields, ulong data_offset) { reg2 uint i; uint int_count, comment_length=0; uchar buff[MAX_FIELD_WIDTH]; - create_field *field; + Create_field *field; DBUG_ENTER("pack_fields"); /* Write field info */ - List_iterator<create_field> it(create_fields); + List_iterator<Create_field> it(create_fields); int_count=0; while ((field=it++)) @@ -756,13 +757,13 @@ static bool pack_fields(File file, List<create_field> &create_fields, int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); - if (my_write(file,(byte*) buff,FCOMP,MYF_RW)) + if (my_write(file, buff, FCOMP, MYF_RW)) DBUG_RETURN(1); } /* Write fieldnames */ buff[0]=(uchar) NAMES_SEP_CHAR; - if (my_write(file,(byte*) buff,1,MYF_RW)) + if (my_write(file, buff, 1, MYF_RW)) DBUG_RETURN(1); i=0; it.rewind(); @@ -772,7 +773,7 @@ static bool pack_fields(File file, List<create_field> &create_fields, *pos++=NAMES_SEP_CHAR; if (i == create_fields.elements-1) *pos++=0; - if (my_write(file,(byte*) buff,(uint) (pos-(char*) buff),MYF_RW)) + if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW)) DBUG_RETURN(1); i++; } @@ -832,7 +833,7 @@ static bool pack_fields(File file, List<create_field> &create_fields, tmp.append('\0'); // End of intervall } } - if (my_write(file,(byte*) tmp.ptr(),tmp.length(),MYF_RW)) + if (my_write(file,(uchar*) tmp.ptr(),tmp.length(),MYF_RW)) DBUG_RETURN(1); } if (comment_length) @@ -842,7 +843,7 @@ static bool pack_fields(File file, List<create_field> &create_fields, while ((field=it++)) { if (field->comment.length) - if (my_write(file, (byte*) field->comment.str, field->comment.length, + if (my_write(file, (uchar*) field->comment.str, field->comment.length, MYF_RW)) DBUG_RETURN(1); } @@ -855,7 +856,7 @@ static bool pack_fields(File file, List<create_field> &create_fields, static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, uint table_options, - List<create_field> &create_fields, + List<Create_field> &create_fields, uint reclength, ulong data_offset, handler *handler) @@ -866,7 +867,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, uchar *buff,*null_pos; TABLE table; TABLE_SHARE share; - create_field *field; + Create_field *field; enum_check_fields old_count_cuted_fields= thd->count_cuted_fields; DBUG_ENTER("make_empty_rec"); @@ -875,7 +876,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, bzero((char*) &share, sizeof(share)); table.s= &share; - if (!(buff=(uchar*) my_malloc((uint) reclength,MYF(MY_WME | MY_ZEROFILL)))) + if (!(buff=(uchar*) my_malloc((size_t) reclength,MYF(MY_WME | MY_ZEROFILL)))) { DBUG_RETURN(1); } @@ -892,7 +893,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, } null_pos= buff; - List_iterator<create_field> it(create_fields); + List_iterator<Create_field> it(create_fields); thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values while ((field=it++)) { @@ -900,7 +901,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, regfield don't have to be deleted as it's allocated with sql_alloc() */ Field *regfield= make_field(&share, - (char*) buff+field->offset + data_offset, + buff+field->offset + data_offset, field->length, null_pos + null_count / 8, null_count & 7, @@ -968,10 +969,10 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, if (null_count & 7) *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1); - error=(int) my_write(file,(byte*) buff, (uint) reclength,MYF_RW); + error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0; err: - my_free((gptr) buff,MYF(MY_FAE)); + my_free(buff, MYF(MY_FAE)); thd->count_cuted_fields= old_count_cuted_fields; DBUG_RETURN(error); } /* make_empty_rec */ diff --git a/sql/unireg.h b/sql/unireg.h index d67fa372083..5b73c6e9caa 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -74,6 +74,7 @@ #define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ #define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */ #define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */ +#define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */ #define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */ #define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3)) |