diff options
author | monty@mysql.com <> | 2004-05-05 17:05:24 +0300 |
---|---|---|
committer | monty@mysql.com <> | 2004-05-05 17:05:24 +0300 |
commit | d21d49a32a1689d2c486a449574e120d7a2f60c4 (patch) | |
tree | 3238bd16530e02dbfef96513749a73b7294880f8 /sql | |
parent | 104fdf607d312bb13f24063d28d993243bf24ca2 (diff) | |
parent | e51887b05082622a1882217b7f8ec8ae7f6b4598 (diff) | |
download | mariadb-git-d21d49a32a1689d2c486a449574e120d7a2f60c4.tar.gz |
Merge with 4.0.19
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 3 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 21 | ||||
-rw-r--r-- | sql/item.cc | 3 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 137 | ||||
-rw-r--r-- | sql/log_event.cc | 16 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/mysqld.cc | 20 | ||||
-rw-r--r-- | sql/slave.cc | 71 | ||||
-rw-r--r-- | sql/slave.h | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 246 | ||||
-rw-r--r-- | sql/sql_base.cc | 8 | ||||
-rw-r--r-- | sql/sql_db.cc | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 12 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 14 | ||||
-rw-r--r-- | sql/structs.h | 3 | ||||
-rw-r--r-- | sql/table.cc | 5 |
17 files changed, 345 insertions, 228 deletions
diff --git a/sql/field.cc b/sql/field.cc index d5499eca075..fdf314972c8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3099,9 +3099,10 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) time_t time_arg; struct tm *l_time; struct tm tm_tmp; + char *to; val_buffer->alloc(field_length+1); - char *to= (char*) val_buffer->ptr(); + to= (char*) val_buffer->ptr(); val_buffer->length(field_length); #ifdef WORDS_BIGENDIAN diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 872a6abef8b..adf3ac0d6a0 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4652,12 +4652,11 @@ the SQL statement in case of an error. */ int ha_innobase::external_lock( /*=======================*/ - /* out: 0 or error code */ + /* out: 0 */ THD* thd, /* in: handle to the user thread */ int lock_type) /* in: lock type */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - int error = 0; trx_t* trx; DBUG_ENTER("ha_innobase::external_lock"); @@ -4725,11 +4724,21 @@ ha_innobase::external_lock( } if (prebuilt->select_lock_type != LOCK_NONE) { + if (thd->in_lock_tables) { + ulint error; + error = row_lock_table_for_mysql(prebuilt); + + if (error != DB_SUCCESS) { + error = convert_error_code_to_mysql( + error, user_thd); + DBUG_RETURN(error); + } + } trx->mysql_n_tables_locked++; } - DBUG_RETURN(error); + DBUG_RETURN(0); } /* MySQL is releasing a table lock */ @@ -4737,6 +4746,9 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; + if (trx->n_tables_locked) { + row_unlock_table_for_mysql(trx); + } /* If the MySQL lock count drops to zero we know that the current SQL statement has ended */ @@ -4768,7 +4780,7 @@ ha_innobase::external_lock( } } - DBUG_RETURN(error); + DBUG_RETURN(0); } /**************************************************************************** @@ -4805,6 +4817,7 @@ innodb_show_status( rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); + my_chsize(fileno(srv_monitor_file), flen, 0, MYF(0)); if(flen > 64000 - 1) { flen = 64000 - 1; } diff --git a/sql/item.cc b/sql/item.cc index e1cdfcf42c0..98e6f02efad 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1354,7 +1354,10 @@ int Item::save_in_field(Field *field, bool no_conversions) str_value.set_quick(buff, sizeof(buff), cs); result=val_str(&str_value); if (null_value) + { + str_value.set_quick(0, 0); return set_field_to_null_with_conversions(field, no_conversions); + } field->set_notnull(); error=field->store(result->ptr(),result->length(),cs); str_value.set_quick(0, 0, cs); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 933995c1d22..6b7a401c31e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1579,7 +1579,7 @@ String *Item_func_soundex::val_str(String *str) char *from= (char *) res->ptr(), *end=from+res->length(); tmp_value.set_charset(cs); - while (from != end && my_isspace(cs,*from)) // Skip pre-space + while (from != end && !my_isalpha(cs,*from)) // Skip pre-space from++; /* purecov: inspected */ if (from == end) return &my_empty_string; // No alpha characters. diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a578abc345a..f22c14c925f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -634,8 +634,8 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, For example, '1.1' -> '1.100000' */ -bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, - uint count, long *values, bool transform_msec) +static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, + uint count, long *values, bool transform_msec) { const char *end=str+length; uint i; @@ -644,10 +644,10 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, for (i=0 ; i < count ; i++) { - long value; + longlong value; const char *start= str; for (value=0; str != end && my_isdigit(cs,*str) ; str++) - value=value*10L + (long) (*str - '0'); + value= value*LL(10) + (longlong) (*str - '0'); if (transform_msec && i == count - 1) // microseconds always last { long msec_length= 6 - (str - start); @@ -662,14 +662,15 @@ 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), - sizeof(long)*i); - bzero((char*) values, sizeof(long)*(count-i)); + sizeof(*values)*i); + bzero((char*) values, sizeof(*values)*(count-i)); break; } } return (str != end); } + longlong Item_func_period_add::val_int() { DBUG_ASSERT(fixed == 1); @@ -929,7 +930,8 @@ longlong Item_func_time_to_sec::val_int() static bool get_interval_value(Item *args,interval_type int_type, String *str_value, INTERVAL *interval) { - long array[5],value; + ulonglong array[5]; + longlong value; const char *str; uint32 length; CHARSET_INFO *cs=str_value->charset(); @@ -941,7 +943,7 @@ static bool get_interval_value(Item *args,interval_type int_type, bzero((char*) interval,sizeof(*interval)); if ((int) int_type <= INTERVAL_MICROSECOND) { - value=(long) args->val_int(); + value= args->val_int(); if (args->null_value) return 1; if (value < 0) @@ -971,16 +973,16 @@ static bool get_interval_value(Item *args,interval_type int_type, switch (int_type) { case INTERVAL_YEAR: - interval->year=value; + interval->year= (ulong) value; break; case INTERVAL_MONTH: - interval->month=value; + interval->month= (ulong) value; break; case INTERVAL_DAY: - interval->day=value; + interval->day= (ulong) value; break; case INTERVAL_HOUR: - interval->hour=value; + interval->hour= (ulong) value; break; case INTERVAL_MICROSECOND: interval->second_part=value; @@ -994,78 +996,78 @@ static bool get_interval_value(Item *args,interval_type int_type, case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->year=array[0]; - interval->month=array[1]; + interval->year= (ulong) array[0]; + interval->month= (ulong) array[1]; break; case INTERVAL_DAY_HOUR: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; break; case INTERVAL_DAY_MICROSECOND: if (get_interval_info(str,length,cs,5,array,1)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; - interval->second=array[3]; - interval->second_part=array[4]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; + interval->second= array[3]; + interval->second_part= array[4]; break; case INTERVAL_DAY_MINUTE: if (get_interval_info(str,length,cs,3,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; break; case INTERVAL_DAY_SECOND: if (get_interval_info(str,length,cs,4,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; - interval->second=array[3]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; + interval->second= array[3]; break; case INTERVAL_HOUR_MICROSECOND: if (get_interval_info(str,length,cs,4,array,1)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; - interval->second=array[2]; - interval->second_part=array[3]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; + interval->second= array[2]; + interval->second_part= array[3]; break; case INTERVAL_HOUR_MINUTE: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; break; case INTERVAL_HOUR_SECOND: if (get_interval_info(str,length,cs,3,array,0)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; - interval->second=array[2]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; + interval->second= array[2]; break; case INTERVAL_MINUTE_MICROSECOND: if (get_interval_info(str,length,cs,3,array,1)) return (1); - interval->minute=array[0]; - interval->second=array[1]; - interval->second_part=array[2]; + interval->minute= array[0]; + interval->second= array[1]; + interval->second_part= array[2]; break; case INTERVAL_MINUTE_SECOND: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->minute=array[0]; - interval->second=array[1]; + interval->minute= array[0]; + interval->second= array[1]; break; case INTERVAL_SECOND_MICROSECOND: if (get_interval_info(str,length,cs,2,array,1)) return (1); - interval->second=array[0]; - interval->second_part=array[1]; + interval->second= array[0]; + interval->second_part= array[1]; break; } return 0; @@ -1639,7 +1641,8 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) case INTERVAL_DAY_SECOND: case INTERVAL_DAY_MINUTE: case INTERVAL_DAY_HOUR: - long sec,days,daynr,microseconds,extra_sec; + { + longlong sec, days, daynr, microseconds, extra_sec; ltime->time_type=TIMESTAMP_DATETIME; // Return full date microseconds= ltime->second_part + sign*interval.second_part; extra_sec= microseconds/1000000L; @@ -1647,40 +1650,44 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+ ltime->second + - sign*(interval.day*3600*24L + - interval.hour*3600+interval.minute*60+interval.second))+ - extra_sec; - + sign* (longlong) (interval.day*3600*24L + + interval.hour*3600+interval.minute*60+ + interval.second))+ extra_sec; if (microseconds < 0) { - microseconds+= 1000000L; + microseconds+= LL(1000000); sec--; } - days=sec/(3600*24L); sec=sec-days*3600*24L; + days= sec/(3600*LL(24)); + sec-= days*3600*LL(24); if (sec < 0) { days--; - sec+=3600*24L; + sec+= 3600*LL(24); } ltime->second_part= microseconds; - ltime->second=sec % 60; - ltime->minute=sec/60 % 60; - ltime->hour=sec/3600; + ltime->second= (uint) (sec % 60); + ltime->minute= (uint) (sec/60 % 60); + ltime->hour= (uint) (sec/3600); daynr= calc_daynr(ltime->year,ltime->month,1) + days; - get_date_from_daynr(daynr,<ime->year,<ime->month,<ime->day); - if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31 + /* Day number from year 0 to 9999-12-31 */ + if ((ulonglong) daynr >= MAX_DAY_NUMBER) goto null_date; + get_date_from_daynr((long) daynr, <ime->year, <ime->month, + <ime->day); break; + } case INTERVAL_DAY: - period= calc_daynr(ltime->year,ltime->month,ltime->day) + - sign*interval.day; - if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31 + period= (calc_daynr(ltime->year,ltime->month,ltime->day) + + sign * (long) interval.day); + /* Daynumber from year 0 to 9999-12-31 */ + if ((ulong) period >= MAX_DAY_NUMBER) goto null_date; get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); break; case INTERVAL_YEAR: - ltime->year += sign*interval.year; - if ((int) ltime->year < 0 || ltime->year >= 10000L) + ltime->year+= sign * (long) interval.year; + if ((ulong) ltime->year >= 10000L) goto null_date; if (ltime->month == 2 && ltime->day == 29 && calc_days_in_year(ltime->year) != 366) @@ -1688,9 +1695,9 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) break; case INTERVAL_YEAR_MONTH: case INTERVAL_MONTH: - period= (ltime->year*12 + sign*interval.year*12 + - ltime->month-1 + sign*interval.month); - if (period < 0 || period >= 120000L) + period= (ltime->year*12 + sign * (long) interval.year*12 + + ltime->month-1 + sign * (long) interval.month); + if ((ulong) period >= 120000L) goto null_date; ltime->year= (uint) (period / 12); ltime->month= (uint) (period % 12L)+1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 207f4a51ff4..b3ec1f0fe55 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -998,11 +998,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { slave_print_error(rli,expected_error, "\ -Query '%s' partially completed on the master (error on master: %d) \ +Query partially completed on the master (error on master: %d) \ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the \ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \ -START SLAVE; .", thd->query, expected_error); +START SLAVE; . Query: '%s'", expected_error, thd->query); thd->query_error= 1; } goto end; @@ -1021,15 +1021,14 @@ START SLAVE; .", thd->query, expected_error); { slave_print_error(rli, 0, "\ -Query '%s' caused different errors on master and slave. \ +Query caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ -Default database: '%s'", - query, +Default database: '%s'. Query: '%s'", ER_SAFE(expected_error), expected_error, actual_error ? thd->net.last_error: "no error", actual_error, - print_slave_db_safe(db)); + print_slave_db_safe(db), query); thd->query_error= 1; } /* @@ -1047,11 +1046,10 @@ Default database: '%s'", else if (thd->query_error || thd->is_fatal_error) { slave_print_error(rli,actual_error, - "Error '%s' on query '%s'. Default database: '%s'", + "Error '%s' on query. Default database: '%s'. Query: '%s'", (actual_error ? thd->net.last_error : "unexpected success or fatal error"), - query, - print_slave_db_safe(db)); + print_slave_db_safe(db), query); thd->query_error= 1; } } /* End of if (db_ok(... */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a5b6bf40c71..8cae95e5070 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1042,8 +1042,7 @@ void reset_host_errors(struct in_addr *in); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); -bool get_interval_info(const char *str,uint length,uint count, - long *values); + /* sql_cache.cc */ extern bool sql_cache_init(); extern void sql_cache_free(); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b85041207bd..c231ec0e024 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2328,6 +2328,15 @@ Warning: you need to use --log-bin to make --log-slave-updates work. \ Now disabling --log-slave-updates."); } + if (opt_log_slave_updates && replicate_same_server_id) + { + sql_print_error("\ +Error: using --replicate-same-server-id in conjunction with \ +--log-slave-updates is impossible, it would lead to infinite loops in this \ +server."); + unireg_abort(1); + } + if (opt_error_log) { if (!log_error_file_ptr[0]) @@ -3616,7 +3625,7 @@ enum options_mysqld OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE, OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE, OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE, - OPT_REPLICATE_WILD_IGNORE_TABLE, + OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID, OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_ABORT_SLAVE_EVENT_COUNT, OPT_INNODB_DATA_HOME_DIR, @@ -4090,6 +4099,13 @@ master-ssl", {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID, + "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, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, // 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.", @@ -4143,7 +4159,7 @@ relay logs.", 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.", + "Show user and password in SHOW SLAVE HOSTS on this master", (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, diff --git a/sql/slave.cc b/sql/slave.cc index 61d5e956e6c..c8da53433d7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -39,7 +39,7 @@ HASH replicate_do_table, replicate_ignore_table; DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; bool do_table_inited = 0, ignore_table_inited = 0; bool wild_do_table_inited = 0, wild_ignore_table_inited = 0; -bool table_rules_on = 0; +bool table_rules_on= 0, replicate_same_server_id; ulonglong relay_log_space_limit = 0; /* @@ -747,7 +747,16 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) Note that changing the order of the tables in the list can lead to different results. Note also the order of precedence of the do/ignore rules (see code below). For that reason, users should not set conflicting - rules because they may get unpredicted results. + rules because they may get unpredicted results (precedence order is + explained in the manual). + If no table of the list is marked "updating" (so far this can only happen + if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables" + is the tables in the FROM): then we always return 0, because there is no + reason we play this statement on this slave if it updates nothing. In the + case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(), + with tables having "updating==TRUE" (those after the DELETE), so this + second call will make the decision (because + all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)). RETURN VALUES 0 should not be logged/replicated @@ -756,6 +765,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) int tables_ok(THD* thd, TABLE_LIST* tables) { + bool some_tables_updating= 0; DBUG_ENTER("tables_ok"); for (; tables; tables = tables->next) @@ -766,6 +776,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables) if (!tables->updating) continue; + some_tables_updating= 1; end= strmov(hash_key, tables->db ? tables->db : thd->db); *end++= '.'; len= (uint) (strmov(end, tables->real_name) - hash_key); @@ -788,10 +799,13 @@ int tables_ok(THD* thd, TABLE_LIST* tables) } /* + If no table was to be updated, ignore statement (no reason we play it on + slave, slave is supposed to replicate _changes_ only). If no explicit rule found and there was a do list, do not replicate. If there was no do list, go ahead */ - DBUG_RETURN(!do_table_inited && !wild_do_table_inited); + DBUG_RETURN(some_tables_updating && + !do_table_inited && !wild_do_table_inited); } @@ -1529,13 +1543,13 @@ Failed to open the existing relay log info file '%s' (errno %d)", rli->info_fd = info_fd; int relay_log_pos, master_log_pos; if (init_strvar_from_file(rli->group_relay_log_name, - sizeof(rli->group_relay_log_name), &rli->info_file, - "") || + sizeof(rli->group_relay_log_name), + &rli->info_file, "") || init_intvar_from_file(&relay_log_pos, &rli->info_file, BIN_LOG_HEADER_SIZE) || init_strvar_from_file(rli->group_master_log_name, - sizeof(rli->group_master_log_name), &rli->info_file, - "") || + sizeof(rli->group_master_log_name), + &rli->info_file, "") || init_intvar_from_file(&master_log_pos, &rli->info_file, 0)) { msg="Error reading slave log configuration"; @@ -2232,7 +2246,8 @@ st_relay_log_info::st_relay_log_info() inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), until_log_pos(0) { - group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; + group_relay_log_name[0]= event_relay_log_name[0]= + group_master_log_name[0]= 0; last_slave_error[0]=0; until_log_name[0]= 0; bzero((char*) &info_file, sizeof(info_file)); @@ -2334,6 +2349,8 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, error= -2; //means improper arguments goto err; } + // Convert 0-3 to 4 + log_pos= max(log_pos, BIN_LOG_HEADER_SIZE); /* p points to '.' */ log_name_extension= strtoul(++p, &p_end, 10); /* @@ -2354,10 +2371,24 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, { bool pos_reached; int cmp_result= 0; - DBUG_ASSERT(*group_master_log_name || group_master_log_pos == 0); + + /* + group_master_log_name can be "", if we are just after a fresh + replication start or after a CHANGE MASTER TO MASTER_HOST/PORT + (before we have executed one Rotate event from the master) or + (rare) if the user is doing a weird slave setup (see next + paragraph). If group_master_log_name is "", we assume we don't + have enough info to do the comparison yet, so we just wait until + more data. In this case master_log_pos is always 0 except if + somebody (wrongly) sets this slave to be a slave of itself + without using --replicate-same-server-id (an unsupported + configuration which does nothing), then group_master_log_pos + will grow and group_master_log_name will stay "". + */ if (*group_master_log_name) { - char *basename= group_master_log_name + dirname_length(group_master_log_name); + char *basename= (group_master_log_name + + dirname_length(group_master_log_name)); /* First compare the parts before the extension. Find the dot in the master's log basename, @@ -2374,14 +2405,15 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, char *q_end; ulong group_master_log_name_extension= strtoul(q, &q_end, 10); if (group_master_log_name_extension < log_name_extension) - cmp_result = -1 ; + cmp_result= -1 ; else cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ; + + pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || + cmp_result > 0); + if (pos_reached || thd->killed) + break; } - pos_reached = ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || - cmp_result > 0); - if (pos_reached || thd->killed) - break; //wait for master update, with optional timeout. @@ -2801,7 +2833,12 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) log files themselves. */ - if (ev->server_id == (uint32) ::server_id || + /* + TODO: when this is merged into 4.1, one needs to update queue_event() to + add a similar test for replicate_same_server_id, because in 4.1 the I/O + thread is also filtering events based on the server id. + */ + if ((ev->server_id == (uint32) ::server_id && !replicate_same_server_id) || (rli->slave_skip_counter && type_code != ROTATE_EVENT)) { /* TODO: I/O thread should not even log events with the same server id */ @@ -3530,8 +3567,8 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, this end 0, which leads to segfault. */ tmp_buf[event_len++]=0; - buf = (const char*)tmp_buf; int4store(tmp_buf+EVENT_LEN_OFFSET, event_len); + buf = (const char*)tmp_buf; } /* This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to diff --git a/sql/slave.h b/sql/slave.h index c925831d1a5..384436fdfcc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -529,7 +529,7 @@ extern HASH replicate_do_table, replicate_ignore_table; extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; extern bool do_table_inited, ignore_table_inited, wild_do_table_inited, wild_ignore_table_inited; -extern bool table_rules_on; +extern bool table_rules_on, replicate_same_server_id; extern int disconnect_slave_event_count, abort_slave_event_count ; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f8dca1133cc..625068e655c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -850,11 +850,11 @@ static void acl_insert_user(const char *user, const char *host, { ACL_USER acl_user; acl_user.user=*user ? strdup_root(&mem,user) : 0; - update_hostname(&acl_user.host,strdup_root(&mem,host)); + update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0); acl_user.access=privileges; acl_user.user_resource = *mqh; acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); - acl_user.hostname_length=(uint) strlen(acl_user.host.hostname); + acl_user.hostname_length=(uint) strlen(host); acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? ssl_type : SSL_TYPE_NONE); acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0; @@ -1705,107 +1705,124 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length, class GRANT_TABLE :public Sql_alloc { public: - char *host,*db,*user,*tname, *hash_key; + char *host,*db, *user, *tname, *hash_key, *orig_host; ulong privs, cols; ulong sort; uint key_length; HASH hash_columns; - GRANT_TABLE (const char *h, const char *d,const char *u, const char *t, - ulong p, ulong c) - : privs(p), cols(c) - { - host = strdup_root(&memex,h); - db = strdup_root(&memex,d); - user = strdup_root(&memex,u); - sort= get_sort(3,host,db,user); - tname= strdup_root(&memex,t); - if (lower_case_table_names) - { - my_casedn_str(&my_charset_latin1, db); - my_casedn_str(&my_charset_latin1, tname); - } - key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; - hash_key = (char*) alloc_root(&memex,key_length); - strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,&my_charset_latin1, - 0,0,0, (hash_get_key) get_key_column,0,0); - } - - GRANT_TABLE (TABLE *form, TABLE *col_privs) - { - byte key[MAX_KEY_LENGTH]; - - host = get_field(&memex,form->field[0]); - db = get_field(&memex,form->field[1]); - user = get_field(&memex,form->field[2]); - if (!user) - user=(char*) ""; - sort= get_sort(3,host,db,user); - tname= get_field(&memex,form->field[3]); - if (!host || !db || !tname) - { - /* Wrong table row; Ignore it */ - privs = cols = 0; /* purecov: inspected */ - return; /* purecov: inspected */ - } - if (lower_case_table_names) - { - my_casedn_str(&my_charset_latin1, db); - my_casedn_str(&my_charset_latin1, tname); - } - key_length = ((uint) strlen(db) + (uint) strlen(user) + - (uint) 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(); - cols = (ulong) form->field[7]->val_int(); - privs = fix_rights_for_table(privs); - cols = fix_rights_for_column(cols); - - (void) hash_init(&hash_columns,&my_charset_latin1, - 0,0,0, (hash_get_key) get_key_column,0,0); - if (cols) - { - int key_len; - col_privs->field[0]->store(host,(uint) strlen(host), &my_charset_latin1); - col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); - col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); - key_len=(col_privs->field[0]->pack_length()+ - col_privs->field[1]->pack_length()+ - col_privs->field[2]->pack_length()+ - col_privs->field[3]->pack_length()); - key_copy(key,col_privs,0,key_len); - col_privs->field[4]->store("",0, &my_charset_latin1); - col_privs->file->index_init(0); - if (col_privs->file->index_read(col_privs->record[0], - (byte*) col_privs->field[0]->ptr, - key_len, HA_READ_KEY_EXACT)) + + GRANT_TABLE(const char *h, const char *d,const char *u, + const char *t, ulong p, ulong c); + GRANT_TABLE (TABLE *form, TABLE *col_privs); + bool ok() { return privs != 0 || cols != 0; } +}; + + + +GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, + const char *t, ulong p, ulong c) + :privs(p), cols(c) +{ + /* Host given by user */ + orig_host= strdup_root(&memex,h); + /* Convert empty hostname to '%' for easy comparision */ + host= orig_host[0] ? orig_host : (char*) "%"; + db = strdup_root(&memex,d); + user = strdup_root(&memex,u); + sort= get_sort(3,host,db,user); + tname= strdup_root(&memex,t); + if (lower_case_table_names) + { + my_casedn_str(&my_charset_latin1, db); + my_casedn_str(&my_charset_latin1, tname); + } + key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; + hash_key = (char*) alloc_root(&memex,key_length); + strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); + (void) hash_init(&hash_columns,&my_charset_latin1, + 0,0,0, (hash_get_key) get_key_column,0,0); +} + + +GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) +{ + byte key[MAX_KEY_LENGTH]; + + orig_host= host= get_field(&memex, form->field[0]); + db= get_field(&memex,form->field[1]); + user= get_field(&memex,form->field[2]); + if (!user) + user= (char*) ""; + if (!orig_host) + { + orig_host= (char*) ""; + host= (char*) "%"; + } + sort= get_sort(3, orig_host, db, user); + tname= get_field(&memex,form->field[3]); + if (!db || !tname) + { + /* Wrong table row; Ignore it */ + privs = cols = 0; /* purecov: inspected */ + return; /* purecov: inspected */ + } + if (lower_case_table_names) + { + my_casedn_str(&my_charset_latin1, db); + my_casedn_str(&my_charset_latin1, tname); + } + key_length = ((uint) strlen(db) + (uint) strlen(user) + + (uint) 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(); + cols = (ulong) form->field[7]->val_int(); + privs = fix_rights_for_table(privs); + cols = fix_rights_for_column(cols); + + (void) hash_init(&hash_columns,&my_charset_latin1, + 0,0,0, (hash_get_key) get_key_column,0,0); + if (cols) + { + int key_len; + col_privs->field[0]->store(orig_host,(uint) strlen(orig_host), + &my_charset_latin1); + col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); + col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); + col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); + key_len=(col_privs->field[0]->pack_length()+ + col_privs->field[1]->pack_length()+ + col_privs->field[2]->pack_length()+ + col_privs->field[3]->pack_length()); + key_copy(key,col_privs,0,key_len); + col_privs->field[4]->store("",0, &my_charset_latin1); + col_privs->file->index_init(0); + if (col_privs->file->index_read(col_privs->record[0], + (byte*) col_privs->field[0]->ptr, + key_len, HA_READ_KEY_EXACT)) + { + cols = 0; /* purecov: deadcode */ + return; + } + do + { + String *res,column_name; + GRANT_COLUMN *mem_check; + /* As column name is a string, we don't have to supply a buffer */ + res=col_privs->field[4]->val_str(&column_name); + ulong priv= (ulong) col_privs->field[6]->val_int(); + if (!(mem_check = new GRANT_COLUMN(*res, + fix_rights_for_column(priv)))) { - cols = 0; /* purecov: deadcode */ - return; + /* Don't use this entry */ + privs = cols = 0; /* purecov: deadcode */ + return; /* purecov: deadcode */ } - do - { - String *res,column_name; - GRANT_COLUMN *mem_check; - /* As column name is a string, we don't have to supply a buffer */ - res=col_privs->field[4]->val_str(&column_name); - ulong priv= (ulong) col_privs->field[6]->val_int(); - if (!(mem_check = new GRANT_COLUMN(*res, - fix_rights_for_column(priv)))) - { - /* Don't use this entry */ - privs = cols = 0; /* purecov: deadcode */ - return; /* purecov: deadcode */ - } - my_hash_insert(&hash_columns, (byte *) mem_check); - } while (!col_privs->file->index_next(col_privs->record[0]) && - !key_cmp(col_privs,key,0,key_len)); - } + my_hash_insert(&hash_columns, (byte *) mem_check); + } while (!col_privs->file->index_next(col_privs->record[0]) && + !key_cmp(col_privs,key,0,key_len)); } - bool ok() { return privs != 0 || cols != 0; } -}; +} static byte* get_grant_table(GRANT_TABLE *buff,uint *length, @@ -2646,7 +2663,7 @@ void grant_reload(THD *thd) /**************************************************************************** - Check grants + Check table level grants All errors are written directly to the client if no_errors is given ! ****************************************************************************/ @@ -3010,9 +3027,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) const char *user,*host; acl_user=dynamic_element(&acl_users,counter,ACL_USER*); if (!(user=acl_user->user)) - user=""; + user= ""; if (!(host=acl_user->host.hostname)) - host="%"; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) break; @@ -3142,9 +3159,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user=acl_db->user)) - user=""; + user= ""; if (!(host=acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) @@ -3195,7 +3212,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } - /* Add column access */ + /* Add table & column access */ for (index=0 ; index < column_priv_hash.records ; index++) { const char *user,*host; @@ -3203,9 +3220,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) index); if (!(user=grant_table->user)) - user=""; - if (!(host=grant_table->host)) - host=""; + user= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) @@ -3225,6 +3240,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append("USAGE",5); else { + /* Add specific column access */ int found= 0; ulong j; @@ -3405,9 +3421,9 @@ ACL_USER *check_acl_user(LEX_USER *user_name, const char *user,*host; acl_user= dynamic_element(&acl_users, counter, ACL_USER*); if (!(user=acl_user->user)) - user=""; + user= ""; if (!(host=acl_user->host.hostname)) - host="%"; + host= "%"; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) break; @@ -3463,9 +3479,9 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) const char *user,*host; acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user= acl_db->user)) - user=""; + user= ""; if (!(host= acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) @@ -3486,9 +3502,9 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, counter); if (!(user=grant_table->user)) - user=""; + user= ""; if (!(host=grant_table->host)) - host=""; + host= ""; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) @@ -3576,9 +3592,9 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user=acl_db->user)) - user=""; + user= ""; if (!(host=acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) @@ -3595,9 +3611,9 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, counter); if (!(user=grant_table->user)) - user=""; + user= ""; if (!(host=grant_table->host)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 75c7a779180..3a18b7eaabc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2607,9 +2607,15 @@ static void mysql_rm_tmp_tables(void) /* Remove all SQLxxx tables from directory */ - for (idx=2 ; idx < (uint) dirp->number_off_files ; idx++) + for (idx=0 ; idx < (uint) dirp->number_off_files ; idx++) { file=dirp->dir_entry+idx; + + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) { sprintf(filePath,"%s%s",tmpdir,file->name); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a6bd1955fa5..bddaebdc0f2 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -462,7 +462,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, tot_list_next= &tot_list; - for (uint idx=2 ; + for (uint idx=0 ; idx < (uint) dirp->number_off_files && !thd->killed ; idx++) { @@ -470,6 +470,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, char *extension; DBUG_PRINT("info",("Examining: %s", file->name)); + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + /* Check if file is a raid directory */ if ((my_isdigit(&my_charset_latin1, file->name[0]) || (file->name[0] >= 'a' && file->name[0] <= 'f')) && diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8185c716228..59c2999863a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -486,6 +486,7 @@ int write_record(TABLE *table,COPY_INFO *info) { int error; char *key=0; + DBUG_ENTER("write_record"); info->records++; if (info->handle_duplicates == DUP_REPLACE || @@ -593,14 +594,14 @@ int write_record(TABLE *table,COPY_INFO *info) info->copied++; if (key) my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH); - return 0; + DBUG_RETURN(0); err: if (key) my_afree(key); info->last_errno= error; table->file->print_error(error,MYF(0)); - return 1; + DBUG_RETURN(1); } @@ -1468,24 +1469,25 @@ select_insert::~select_insert() bool select_insert::send_data(List<Item> &values) { + DBUG_ENTER("select_insert::send_data"); if (unit->offset_limit_cnt) { // using limit offset,count unit->offset_limit_cnt--; - return 0; + DBUG_RETURN(0); } if (fields->elements) fill_record(*fields, values, 1); else fill_record(table->field, values, 1); if (thd->net.report_error || write_record(table,&info)) - return 1; + DBUG_RETURN(1); if (table->next_number_field) // Clear for next record { table->next_number_field->reset(); if (! last_insert_id && thd->insert_id_used) last_insert_id=thd->insert_id(); } - return 0; + DBUG_RETURN(0); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 568a526fd58..86b4702d314 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1176,7 +1176,7 @@ field_list_item: ; column_def: - field_spec check_constraint + field_spec opt_check_constraint | field_spec references { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -1208,15 +1208,23 @@ key_def: lex->fk_match_option)); lex->col_list.empty(); /* Alloced by sql_alloc */ } + | constraint opt_check_constraint + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ } ; -check_constraint: +opt_check_constraint: /* empty */ - | CHECK_SYM expr + | check_constraint + ; + +check_constraint: + CHECK_SYM expr ; opt_constraint: diff --git a/sql/structs.h b/sql/structs.h index d9607b220f7..ee231186e1a 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -150,7 +150,8 @@ typedef struct st_time { typedef struct { - long year,month,day,hour,minute,second,second_part; + ulong year,month,day,hour; + ulonglong minute,second,second_part; bool neg; } INTERVAL; diff --git a/sql/table.cc b/sql/table.cc index 281a8c10409..73f036aed87 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1140,6 +1140,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, if (create_info->min_rows > ~(ulong) 0) create_info->min_rows= ~(ulong) 0; #endif + /* + Ensure that raid_chunks can't be larger than 255, as this would cause + problems with drop database + */ + set_if_smaller(create_info->raid_chunks, 255); if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { |