From 3231241f837729781339f68c270252ac80d11a52 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 15:58:34 +0300 Subject: [PATCH 01/16] Rename decimal -> decimal_t, decimal_digit -> decimal_digit_t --- include/decimal.h | 55 ++++++++++++++------------- sql/log_event.cc | 6 +-- sql/my_decimal.cc | 4 +- sql/my_decimal.h | 46 +++++++++++------------ strings/decimal.c | 94 ++++++++++++++++++++++++----------------------- 5 files changed, 106 insertions(+), 99 deletions(-) diff --git a/include/decimal.h b/include/decimal.h index 3f4a2122c57..7b49841ca88 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -20,47 +20,50 @@ typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode; -typedef int32 decimal_digit; +typedef int32 decimal_digit_t; -typedef struct st_decimal { +typedef struct st_decimal_t { int intg, frac, len; my_bool sign; - decimal_digit *buf; -} decimal; + decimal_digit_t *buf; +} decimal_t; -int internal_str2dec(const char *from, decimal *to, char **end, my_bool fixed); -int decimal2string(decimal *from, char *to, int *to_len, +int internal_str2dec(const char *from, decimal_t *to, char **end, + my_bool fixed); +int decimal2string(decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler); -int decimal2ulonglong(decimal *from, ulonglong *to); -int ulonglong2decimal(ulonglong from, decimal *to); -int decimal2longlong(decimal *from, longlong *to); -int longlong2decimal(longlong from, decimal *to); -int decimal2double(decimal *from, double *to); -int double2decimal(double from, decimal *to); -void decimal_optimize_fraction(decimal *from); -int decimal2bin(decimal *from, char *to, int precision, int scale); -int bin2decimal(char *from, decimal *to, int precision, int scale); +int decimal2ulonglong(decimal_t *from, ulonglong *to); +int ulonglong2decimal(ulonglong from, decimal_t *to); +int decimal2longlong(decimal_t *from, longlong *to); +int longlong2decimal(longlong from, decimal_t *to); +int decimal2double(decimal_t *from, double *to); +int double2decimal(double from, decimal_t *to); +void decimal_optimize_fraction(decimal_t *from); +int decimal2bin(decimal_t *from, char *to, int precision, int scale); +int bin2decimal(char *from, decimal_t *to, int precision, int scale); int decimal_size(int precision, int scale); int decimal_bin_size(int precision, int scale); -int decimal_result_size(decimal *from1, decimal *from2, char op, int param); +int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, + int param); -int decimal_add(decimal *from1, decimal *from2, decimal *to); -int decimal_sub(decimal *from1, decimal *from2, decimal *to); -int decimal_cmp(decimal *from1, decimal *from2); -int decimal_mul(decimal *from1, decimal *from2, decimal *to); -int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr); -int decimal_mod(decimal *from1, decimal *from2, decimal *to); -int decimal_round(decimal *from, decimal *to, int new_scale, +int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_cmp(decimal_t *from1, decimal_t *from2); +int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, + int scale_incr); +int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_round(decimal_t *from, decimal_t *to, int new_scale, decimal_round_mode mode); -int decimal_is_zero(decimal *from); -void max_decimal(int precision, int frac, decimal *to); +int decimal_is_zero(decimal_t *from); +void max_decimal(int precision, int frac, decimal_t *to); #define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) #define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) -/* set a decimal to zero */ +/* set a decimal_t to zero */ #define decimal_make_zero(dec) do { \ (dec)->buf[0]=0; \ diff --git a/sql/log_event.cc b/sql/log_event.cc index ba018e859c1..3581626ca5b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3336,7 +3336,7 @@ bool User_var_log_event::write(IO_CACHE* file) dec->fix_buffer_pointer(); buf2[0]= (char)(dec->intg + dec->frac); buf2[1]= (char)dec->frac; - decimal2bin((decimal*)val, buf2+2, buf2[0], buf2[1]); + decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]); val_len= decimal_bin_size(buf2[0], buf2[1]) + 2; break; } @@ -3403,8 +3403,8 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las int str_len= sizeof(str_buf) - 1; int precision= (int)val[0]; int scale= (int)val[1]; - decimal_digit dec_buf[10]; - decimal dec; + decimal_digit_t dec_buf[10]; + decimal_t dec; dec.len= 10; dec.buf= dec_buf; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 334c40c0f70..19b6abd7243 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -88,7 +88,7 @@ int my_decimal2string(uint mask, const my_decimal *d, int result; if (str->alloc(length)) return check_result(mask, E_DEC_OOM); - result= decimal2string((decimal*) d, (char*) str->ptr(), + result= decimal2string((decimal_t*) d, (char*) str->ptr(), &length, fixed_prec, fixed_dec, filler); str->length(length); @@ -172,7 +172,7 @@ int str2my_decimal(uint mask, const char *from, uint length, charset= &my_charset_bin; } from_end= end= (char*) from+length; - err= string2decimal((char *)from, (decimal *)decimal_value, &end); + err= string2decimal((char *)from, (decimal_t*) decimal_value, &end); if (end != from_end && !err) { /* Give warining if there is something other than end space */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 44530acd0cc..03801390d82 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -69,15 +69,15 @@ inline uint my_decimal_size(uint precision, uint scale) /* - my_decimal class limits 'decimal' type to what we need in MySQL + my_decimal class limits 'decimal_t' type to what we need in MySQL It contains internally all necessary space needed by the instance so no extra memory is needed. One should call fix_buffer_pointer() function when he moves my_decimal objects in memory */ -class my_decimal :public decimal +class my_decimal :public decimal_t { - decimal_digit buffer[DECIMAL_BUFF_LENGTH]; + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; public: @@ -97,8 +97,8 @@ public: } void fix_buffer_pointer() { buf= buffer; } - bool sign() const { return decimal::sign; } - void sign(bool s) { decimal::sign= s; } + bool sign() const { return decimal_t::sign; } + void sign(bool s) { decimal_t::sign= s; } }; @@ -165,7 +165,7 @@ inline int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, int scale) { - return check_result(mask, bin2decimal((char *)bin, (decimal*) d, prec, + return check_result(mask, bin2decimal((char *)bin, (decimal_t*) d, prec, scale)); } @@ -173,7 +173,7 @@ int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, inline int my_decimal_set_zero(my_decimal *d) { - decimal_make_zero(((decimal*) d)); + decimal_make_zero(((decimal_t*) d)); return 0; } @@ -181,7 +181,7 @@ int my_decimal_set_zero(my_decimal *d) inline bool my_decimal_is_zero(const my_decimal *decimal_value) { - return decimal_is_zero((decimal*) decimal_value); + return decimal_is_zero((decimal_t*) decimal_value); } @@ -189,7 +189,7 @@ inline int my_decimal_round(uint mask, const my_decimal *from, int scale, bool truncate, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, scale, + return check_result(mask, decimal_round((decimal_t*) from, to, scale, (truncate ? TRUNCATE : HALF_UP))); } @@ -197,14 +197,14 @@ int my_decimal_round(uint mask, const my_decimal *from, int scale, inline int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, FLOOR)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR)); } inline int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, CEILING)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING)); } @@ -219,7 +219,7 @@ int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag, { my_decimal rounded; /* decimal_round can return only E_DEC_TRUNCATED */ - decimal_round((decimal*)d, &rounded, 0, HALF_UP); + decimal_round((decimal_t*)d, &rounded, 0, HALF_UP); return check_result(mask, (unsigned_flag ? decimal2ulonglong(&rounded, (ulonglong *)l) : decimal2longlong(&rounded, l))); @@ -230,14 +230,14 @@ inline int my_decimal2double(uint mask, const my_decimal *d, double *result) { /* No need to call check_result as this will always succeed */ - return decimal2double((decimal*) d, result); + return decimal2double((decimal_t*) d, result); } inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { - return check_result(mask, string2decimal(str, (decimal*) d, end)); + return check_result(mask, string2decimal(str, (decimal_t*) d, end)); } @@ -255,7 +255,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) inline int double2my_decimal(uint mask, double val, my_decimal *d) { - return check_result(mask, double2decimal(val, (decimal*) d)); + return check_result(mask, double2decimal(val, (decimal_t*) d)); } @@ -269,7 +269,7 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d) inline -void my_decimal_neg(st_decimal *arg) +void my_decimal_neg(decimal_t *arg) { decimal_neg(arg); } @@ -279,7 +279,7 @@ inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_add((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res)); } @@ -287,7 +287,7 @@ inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_sub((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res)); } @@ -295,7 +295,7 @@ inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mul((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res)); } @@ -303,7 +303,7 @@ inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { - return check_result(mask, decimal_div((decimal*) a, (decimal*) b, res, + return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res, div_scale_inc)); } @@ -312,7 +312,7 @@ inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mod((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res)); } @@ -320,14 +320,14 @@ int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) { - return decimal_cmp((decimal*) a, (decimal*) b); + return decimal_cmp((decimal_t*) a, (decimal_t*) b); } inline void max_my_decimal(my_decimal *to, int precision, int frac) { DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH); - max_decimal(precision, frac, (decimal*) to); + max_decimal(precision, frac, (decimal_t*) to); } #endif /*my_decimal_h*/ diff --git a/strings/decimal.c b/strings/decimal.c index f288a93eb5e..d7bea3e291d 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -109,20 +109,20 @@ /* Internally decimal numbers are stored base 10^9 (see DIG_BASE below) - So one "decimal_digit" is + So one variable of type decimal_digit_t is limited: 0 < decimal_digit <= DIG_MAX < DIG_BASE - in the struct st_decimal: + in the struct st_decimal_t: - intg is the number of *decimal* digits (NOT number of decimal_digit's !) + intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) before the point frac - number of decimal digits after the point - buf is an array of decimal_digit's - len is the length of buf (length of allocated space) in decimal_digit's, + buf is an array of decimal_digit_t's + len is the length of buf (length of allocated space) in decimal_digit_t's, not in bytes */ -typedef decimal_digit dec1; +typedef decimal_digit_t dec1; typedef longlong dec2; #define DIG_PER_DEC1 9 @@ -223,7 +223,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ to->buf and to->len must be set. */ -void max_decimal(int precision, int frac, decimal *to) +void max_decimal(int precision, int frac, decimal_t *to) { int intpart; dec1 *buf= to->buf; @@ -250,7 +250,7 @@ void max_decimal(int precision, int frac, decimal *to) } -static dec1 *remove_leading_zeroes(decimal *from, int *intg_result) +static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result) { int intg= from->intg, i; dec1 *buf0= from->buf; @@ -281,7 +281,7 @@ static dec1 *remove_leading_zeroes(decimal *from, int *intg_result) from number for processing */ -void decimal_optimize_fraction(decimal *from) +void decimal_optimize_fraction(decimal_t *from) { int frac= from->frac, i; dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1; @@ -328,7 +328,7 @@ void decimal_optimize_fraction(decimal *from) E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW */ -int decimal2string(decimal *from, char *to, int *to_len, +int decimal2string(decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler) { @@ -453,7 +453,7 @@ int decimal2string(decimal *from, char *to, int *to_len, be written by this address */ -static void digits_bounds(decimal *from, int *start_result, int *end_result) +static void digits_bounds(decimal_t *from, int *start_result, int *end_result) { int start, stop, i; dec1 *buf_beg= from->buf; @@ -520,7 +520,7 @@ static void digits_bounds(decimal *from, int *start_result, int *end_result) 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive) */ -void do_mini_left_shift(decimal *dec, int shift, int beg, int last) +void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last) { dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1; dec1 *end= dec->buf + ROUND_UP(last) - 1; @@ -550,7 +550,7 @@ void do_mini_left_shift(decimal *dec, int shift, int beg, int last) 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive) */ -void do_mini_right_shift(decimal *dec, int shift, int beg, int last) +void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last) { dec1 *from= dec->buf + ROUND_UP(last) - 1; dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1; @@ -583,7 +583,7 @@ void do_mini_right_shift(decimal *dec, int shift, int beg, int last) E_DEC_TRUNCATED number was rounded to fit into buffer */ -int decimal_shift(decimal *dec, int shift) +int decimal_shift(decimal_t *dec, int shift) { /* index of first non zero digit (all indexes from 0) */ int beg; @@ -780,7 +780,8 @@ int decimal_shift(decimal *dec, int shift) (to make error handling easier) */ -int internal_str2dec(const char *from, decimal *to, char **end, my_bool fixed) +int +internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed) { const char *s= from, *s1, *endp, *end_of_string= *end; int i, intg, frac, error, intg1, frac1; @@ -937,7 +938,7 @@ fatal_error: E_DEC_OK */ -int decimal2double(decimal *from, double *to) +int decimal2double(decimal_t *from, double *to) { double x=0, t=DIG_BASE; int intg, frac; @@ -963,7 +964,7 @@ int decimal2double(decimal *from, double *to) E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED */ -int double2decimal(double from, decimal *to) +int double2decimal(double from, decimal_t *to) { /* TODO: fix it, when we'll have dtoa */ char s[400], *end; @@ -972,7 +973,7 @@ int double2decimal(double from, decimal *to) return string2decimal(s, to, &end); } -static int ull2dec(ulonglong from, decimal *to) +static int ull2dec(ulonglong from, decimal_t *to) { int intg1, error=E_DEC_OK; ulonglong x=from; @@ -998,20 +999,20 @@ static int ull2dec(ulonglong from, decimal *to) return error; } -int ulonglong2decimal(ulonglong from, decimal *to) +int ulonglong2decimal(ulonglong from, decimal_t *to) { to->sign=0; return ull2dec(from, to); } -int longlong2decimal(longlong from, decimal *to) +int longlong2decimal(longlong from, decimal_t *to) { if ((to->sign= from < 0)) return ull2dec(-from, to); return ull2dec(from, to); } -int decimal2ulonglong(decimal *from, ulonglong *to) +int decimal2ulonglong(decimal_t *from, ulonglong *to) { dec1 *buf=from->buf; ulonglong x=0; @@ -1040,7 +1041,7 @@ int decimal2ulonglong(decimal *from, ulonglong *to) return E_DEC_OK; } -int decimal2longlong(decimal *from, longlong *to) +int decimal2longlong(decimal_t *from, longlong *to) { dec1 *buf=from->buf; longlong x=0; @@ -1112,7 +1113,7 @@ int decimal2longlong(decimal *from, longlong *to) 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced number of bytes (enough bytes to store this number of digits - see dig2bytes) - 4. same for frac - full decimal_digit's are stored as is, + 4. same for frac - full decimal_digit_t's are stored as is, the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes. 5. If the number is negative - every byte is inversed. 5. The very first bit of the resulting byte array is inverted (because @@ -1122,7 +1123,7 @@ int decimal2longlong(decimal *from, longlong *to) 1234567890.1234 - internally is represented as 3 decimal_digit's + internally is represented as 3 decimal_digit_t's 1 234567890 123400000 @@ -1131,13 +1132,13 @@ int decimal2longlong(decimal *from, longlong *to) 00-00-00-01 0D-FB-38-D2 07-5A-EF-40 - now, middle decimal_digit is full - it stores 9 decimal digits. It goes + now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes into binary representation as is: ........... 0D-FB-38-D2 ............ - First decimal_digit has only one decimal digit. We can store one digit in + First decimal_digit_t has only one decimal digit. We can store one digit in one byte, no need to waste four: 01 0D-FB-38-D2 ............ @@ -1155,7 +1156,7 @@ int decimal2longlong(decimal *from, longlong *to) 7E F2 04 37 2D FB 2D */ -int decimal2bin(decimal *from, char *to, int precision, int frac) +int decimal2bin(decimal_t *from, char *to, int precision, int frac) { dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1; int error=E_DEC_OK, intg=precision-frac, @@ -1283,7 +1284,7 @@ int decimal2bin(decimal *from, char *to, int precision, int frac) E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW */ -int bin2decimal(char *from, decimal *to, int precision, int scale) +int bin2decimal(char *from, decimal_t *to, int precision, int scale) { int error=E_DEC_OK, intg=precision-scale, intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, @@ -1424,7 +1425,9 @@ int decimal_bin_size(int precision, int scale) E_DEC_OK/E_DEC_TRUNCATED */ -int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode) +int +decimal_round(decimal_t *from, decimal_t *to, int scale, + decimal_round_mode mode) { int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, frac1=ROUND_UP(from->frac), round_digit, @@ -1585,7 +1588,7 @@ done: multiply by sizeof(dec1) */ -int decimal_result_size(decimal *from1, decimal *from2, char op, int param) +int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param) { switch (op) { case '-': @@ -1604,7 +1607,7 @@ int decimal_result_size(decimal *from1, decimal *from2, char op, int param) return -1; /* shut up the warning */ } -static int do_add(decimal *from1, decimal *from2, decimal *to) +static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), @@ -1680,7 +1683,7 @@ static int do_add(decimal *from1, decimal *from2, decimal *to) /* to=from1-from2. if to==0, return -1/0/+1 - the result of the comparison */ -static int do_sub(decimal *from1, decimal *from2, decimal *to) +static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac); @@ -1741,7 +1744,7 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to) /* ensure that always from1 > from2 (and intg1 >= intg2) */ if (carry) { - swap_variables(decimal *,from1,from1); + swap_variables(decimal_t *,from1,from1); swap_variables(dec1 *,start1, start2); swap_variables(int,intg1,intg2); swap_variables(int,frac1,frac2); @@ -1807,28 +1810,28 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to) return error; } -int decimal_add(decimal *from1, decimal *from2, decimal *to) +int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to) { if (likely(from1->sign == from2->sign)) return do_add(from1, from2, to); return do_sub(from1, from2, to); } -int decimal_sub(decimal *from1, decimal *from2, decimal *to) +int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to) { if (likely(from1->sign == from2->sign)) return do_sub(from1, from2, to); return do_add(from1, from2, to); } -int decimal_cmp(decimal *from1, decimal *from2) +int decimal_cmp(decimal_t *from1, decimal_t *from2) { if (likely(from1->sign == from2->sign)) return do_sub(from1, from2, 0); return from1->sign > from2->sign ? -1 : 1; } -int decimal_is_zero(decimal *from) +int decimal_is_zero(decimal_t *from) { dec1 *buf1=from->buf, *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac); @@ -1859,7 +1862,7 @@ int decimal_is_zero(decimal *from) XXX if this library is to be used with huge numbers of thousands of digits, fast multiplication must be implemented. */ -int decimal_mul(decimal *from1, decimal *from2, decimal *to) +int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), @@ -1932,8 +1935,8 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to) changed to malloc (or at least fallback to malloc if alloca() fails) but then, decimal_mod() should be rewritten too :( */ -static int do_div_mod(decimal *from1, decimal *from2, - decimal *to, decimal *mod, int scale_incr) +static int do_div_mod(decimal_t *from1, decimal_t *from2, + decimal_t *to, decimal_t *mod, int scale_incr) { int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1, frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2, @@ -2208,7 +2211,8 @@ done: see do_div_mod() */ -int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr) +int +decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr) { return do_div_mod(from1, from2, to, 0, scale_incr); } @@ -2240,7 +2244,7 @@ int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr) thus, there's no requirement for M or N to be integers */ -int decimal_mod(decimal *from1, decimal *from2, decimal *to) +int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to) { return do_div_mod(from1, from2, 0, to, 0); } @@ -2248,10 +2252,10 @@ int decimal_mod(decimal *from1, decimal *from2, decimal *to) #ifdef MAIN int full= 0; -decimal a, b, c; +decimal_t a, b, c; char buf1[100], buf2[100], buf3[100]; -void dump_decimal(decimal *d) +void dump_decimal(decimal_t *d) { int i; printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign); @@ -2271,7 +2275,7 @@ void check_result_code(int actual, int want) } -void print_decimal(decimal *d, const char *orig, int actual, int want) +void print_decimal(decimal_t *d, const char *orig, int actual, int want) { char s[100]; int slen=sizeof(s); From a94a62cefb4e2c25c0543a7a0741388d48b5e435 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 16:01:39 +0100 Subject: [PATCH 02/16] mtr_report.pl: Made --timer work mtr_cases.pl: Added option --reorder to get less server restarts mysql-test-run.pl: Added option --reorder to get less server restarts Moved do_before_start_master() not to remove binlog files unless restarted Made --timer work Slave was incorrectly writing log to error log mysql-test/mysql-test-run.pl: Added option --reorder to get less server restarts Moved do_before_start_master() not to remove binlog files unless restarted Made --timer work Slave was incorrectly writing log to error log mysql-test/lib/mtr_cases.pl: Added option --reorder to get less server restarts mysql-test/lib/mtr_report.pl: Made --timer work --- mysql-test/lib/mtr_cases.pl | 33 ++++++++++++++++++--------------- mysql-test/lib/mtr_report.pl | 11 +++++------ mysql-test/mysql-test-run.pl | 30 +++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 5977bb380cf..878afe95f2c 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -63,21 +63,24 @@ sub collect_test_cases ($) { # To speed things up, we sort first in if the test require a restart # or not, second in alphanumeric order. -# @$cases = sort { -# if ( $a->{'master_restart'} and $b->{'master_restart'} or -# ! $a->{'master_restart'} and ! $b->{'master_restart'} ) -# { -# return $a->{'name'} cmp $b->{'name'}; -# } -# if ( $a->{'master_restart'} ) -# { -# return 1; # Is greater -# } -# else -# { -# return -1; # Is less -# } -# } @$cases; + if ( $::opt_reorder ) + { + @$cases = sort { + if ( $a->{'master_restart'} and $b->{'master_restart'} or + ! $a->{'master_restart'} and ! $b->{'master_restart'} ) + { + return $a->{'name'} cmp $b->{'name'}; + } + if ( $a->{'master_restart'} ) + { + return 1; # Is greater + } + else + { + return -1; # Is less + } + } @$cases; + } return $cases; } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 9947fed9d27..fd665b154b8 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -89,12 +89,11 @@ sub mtr_report_test_passed ($) { my $tinfo= shift; my $timer= ""; -# FIXME -# if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) -# { -# $timer= `cat var/log/timer`; -# $timer= sprintf "%13s", $timer; -# } + if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) + { + $timer= mtr_fromfile("$::glob_mysql_test_dir/var/log/timer"); + $timer= sprintf "%12s", $timer; + } $tinfo->{'result'}= 'MTR_RES_PASSED'; print "[ pass ] $timer\n"; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f8adf372585..80ba98e4e97 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -214,6 +214,7 @@ our $opt_embedded_server; our $opt_extern; our $opt_fast; our $opt_force; +our $opt_reorder; our $opt_gcov; our $opt_gcov_err; @@ -525,6 +526,7 @@ sub command_line_setup () { 'local-master' => \$opt_local_master, 'netware' => \$opt_netware, 'old-master' => \$opt_old_master, + 'reorder' => \$opt_reorder, 'script-debug' => \$opt_script_debug, 'sleep=i' => \$opt_sleep, 'socket=s' => \$opt_socket, @@ -1368,7 +1370,10 @@ sub run_testcase ($) { mtr_report_test_name($tinfo); mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - do_before_start_master($tname,$tinfo->{'master_sh'}); + +# FIXME test cases that depend on each other, prevent this from +# being at this location. +# do_before_start_master($tname,$tinfo->{'master_sh'}); # ---------------------------------------------------------------------- # If any mysqld servers running died, we have to know @@ -1400,6 +1405,8 @@ sub run_testcase ($) { } if ( ! $master->[0]->{'pid'} ) { + # FIXME not correct location for do_before_start_master() + do_before_start_master($tname,$tinfo->{'master_sh'}); $master->[0]->{'pid'}= mysqld_start('master',0,$tinfo->{'master_opt'},[]); if ( ! $master->[0]->{'pid'} ) @@ -1535,9 +1542,10 @@ sub do_before_start_master ($$) { $tname ne "rpl_crash_binlog_ib_3b") { # FIXME we really want separate dir for binlogs - # FIXME replace 'rm' in backticks with portable Perl function - `rm -f $glob_mysql_test_dir/var/log/master-bin*`; -# unlink("$glob_mysql_test_dir/var/log/master-bin*"); + foreach my $bin ( glob("$glob_mysql_test_dir/var/log/master*-bin.*") ) + { + unlink($bin); + } } # Remove old master.info and relay-log.info files @@ -1571,9 +1579,10 @@ sub do_before_start_slave ($$) { $tname ne "rpl_crash_binlog_ib_3b" ) { # FIXME we really want separate dir for binlogs - # FIXME replace 'rm' in backticks with portable Perl function - `rm -fr $glob_mysql_test_dir/var/log/slave*-bin.*`; -# unlink("$glob_mysql_test_dir/var/log/slave*-bin.*"); # FIXME idx??? + foreach my $bin ( glob("$glob_mysql_test_dir/var/log/slave*-bin.*") ) + { + unlink($bin); + } # FIXME really master?! unlink("$glob_mysql_test_dir/var/slave-data/master.info"); unlink("$glob_mysql_test_dir/var/slave-data/relay-log.info"); @@ -1659,13 +1668,15 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--datadir=%s", $prefix, $slave->[$idx]->{'path_myddir'}); + % FIXME slave get this option twice?! mtr_add_arg($args, "%s--exit-info=256", $prefix); mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix); mtr_add_arg($args, "%s--log-bin=%s/var/log/slave%s-bin", $prefix, $glob_mysql_test_dir, $sidx); # FIXME use own dir for binlogs mtr_add_arg($args, "%s--log-slave-updates", $prefix); + % FIXME option duplicated for slave mtr_add_arg($args, "%s--log=%s", $prefix, - $slave->[$idx]->{'path_myerr'}); + $slave->[$idx]->{'path_mylog'}); mtr_add_arg($args, "%s--master-retry-count=10", $prefix); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $slave->[$idx]->{'path_mypid'}); @@ -2046,7 +2057,7 @@ sub run_mysqltest ($$) { if ( $opt_timer ) { - mtr_add_arg($args, "--timer-file=var/log/timer"); + mtr_add_arg($args, "--timer-file=%s/var/log/timer", $glob_mysql_test_dir); } if ( $opt_big_test ) @@ -2175,6 +2186,7 @@ Misc options timer Show test case execution time start-and-exit Only initiate and start the "mysqld" servers fast Don't try to cleanup from earlier runs + reorder Reorder tests to get less server restarts help Get this help text unified-diff | udiff When presenting differences, use unified diff From 04a410d4e9a502f9950688fefd35451a84d0f1d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 16:31:15 +0100 Subject: [PATCH 03/16] Code cleanup: should use 'element_count' here, see include/my_tree.h (Change done by Ramil and sent via IRC) --- sql/item_sum.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index dd95a83a921..8ee9dc0859b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2158,7 +2158,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) } -static int count_distinct_walk(void *elem, unsigned int count, void *arg) +static int count_distinct_walk(void *elem, element_count count, void *arg) { (*((ulonglong*)arg))++; return 0; From 4b486adf6883a11c4a69f2b852d5048dcf7b30ba Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 16:37:19 +0100 Subject: [PATCH 04/16] init_db.sql: Added 'proc' and 'procs_priv' tables, updated others mysql-test/lib/init_db.sql: Added 'proc' and 'procs_priv' tables, updated others --- mysql-test/lib/init_db.sql | 93 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index 902af0b0842..e3bf669db4e 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -16,6 +16,11 @@ CREATE TABLE db ( Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM @@ -23,8 +28,8 @@ CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; -INSERT INTO db VALUES ('%','test' ,'','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); -INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); CREATE TABLE host ( @@ -42,6 +47,8 @@ CREATE TABLE host ( Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin @@ -73,6 +80,10 @@ CREATE TABLE user ( Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, @@ -80,15 +91,16 @@ CREATE TABLE user ( max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, + max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -INSERT INTO user VALUES ('localhost' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); -INSERT INTO user VALUES ('@HOSTNAME@%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); -REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('localhost' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +INSERT INTO user VALUES ('@HOSTNAME@%' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); INSERT INTO user (host,user) VALUES ('localhost',''); INSERT INTO user (host,user) VALUES ('@HOSTNAME@%',''); @@ -468,3 +480,74 @@ INSERT INTO time_zone_leap_second ( ,(662688015, 16) ,(709948816, 17) ,(741484817, 18) ,(773020818, 19) ,(820454419, 20) ,(867715220, 21) ,(915148821, 22); + + +CREATE TABLE procs_priv ( + Host char(60) binary DEFAULT '' NOT NULL, + Db char(64) binary DEFAULT '' NOT NULL, + User char(16) binary DEFAULT '' NOT NULL, + Routine_name char(64) binary DEFAULT '' NOT NULL, + Grantor char(77) DEFAULT '' NOT NULL, + Timestamp timestamp(14), + Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, + PRIMARY KEY (Host,Db,User,Routine_name), + KEY Grantor (Grantor) +) engine=MyISAM +CHARACTER SET utf8 COLLATE utf8_bin +comment='Procedure privileges'; + + +CREATE TABLE proc ( + db char(64) binary DEFAULT '' NOT NULL, + name char(64) DEFAULT '' NOT NULL, + type enum('FUNCTION','PROCEDURE') NOT NULL, + specific_name char(64) DEFAULT '' NOT NULL, + language enum('SQL') DEFAULT 'SQL' NOT NULL, + sql_data_access enum('CONTAINS_SQL', + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL, + is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, + security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, + param_list blob DEFAULT '' NOT NULL, + returns char(64) DEFAULT '' NOT NULL, + body blob DEFAULT '' NOT NULL, + definer char(77) binary DEFAULT '' NOT NULL, + created timestamp, + modified timestamp, + sql_mode set( + 'REAL_AS_FLOAT', + 'PIPES_AS_CONCAT', + 'ANSI_QUOTES', + 'IGNORE_SPACE', + 'NOT_USED', + 'ONLY_FULL_GROUP_BY', + 'NO_UNSIGNED_SUBTRACTION', + 'NO_DIR_IN_CREATE', + 'POSTGRESQL', + 'ORACLE', + 'MSSQL', + 'DB2', + 'MAXDB', + 'NO_KEY_OPTIONS', + 'NO_TABLE_OPTIONS', + 'NO_FIELD_OPTIONS', + 'MYSQL323', + 'MYSQL40', + 'ANSI', + 'NO_AUTO_VALUE_ON_ZERO', + 'NO_BACKSLASH_ESCAPES', + 'STRICT_TRANS_TABLES', + 'STRICT_ALL_TABLES', + 'NO_ZERO_IN_DATE', + 'NO_ZERO_DATE', + 'INVALID_DATES', + 'ERROR_FOR_DIVISION_BY_ZERO', + 'TRADITIONAL', + 'NO_AUTO_CREATE_USER', + 'HIGH_NOT_PRECEDENCE' + ) DEFAULT 0 NOT NULL, + comment char(64) binary DEFAULT '' NOT NULL, + PRIMARY KEY (db,name,type) +) comment='Stored Procedures'; From 4da513f5e7224f575dcb12f3b6cb5c323b5210b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 18:11:11 +0200 Subject: [PATCH 05/16] A fix for Netware. --- include/config-netware.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/config-netware.h b/include/config-netware.h index 3e145f566a1..c48aff70f3b 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -79,6 +79,9 @@ extern "C" { /* On NetWare, stack grows towards lower address*/ #define STACK_DIRECTION -1 +/* On NetWare, to fix the problem with the deletion of open files */ +#define CANT_DELETE_OPEN_FILES 1 + /* default directory information */ #define DEFAULT_MYSQL_HOME "sys:/mysql" #define PACKAGE "mysql" From 3557a52ad959b916021c6abdf95726409999f89d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 19:10:02 +0100 Subject: [PATCH 06/16] configure.in: 5.0.3 is a beta configure.in: 5.0.3 is a beta --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9a58e0c9b8c..66ca3464615 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.50)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.3-alpha) +AM_INIT_AUTOMAKE(mysql, 5.0.3-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,7 +18,7 @@ SHARED_LIB_VERSION=14:0:0 NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 NDB_VERSION_BUILD=3 -NDB_VERSION_STATUS="alpha" +NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 From 7656b6da717418b1f87fa7bec1c81ccdb6892442 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 22:10:42 +0200 Subject: [PATCH 07/16] trx0trx.c, trx0trx.h: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql() (Bug #9277) innobase/include/trx0trx.h: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql() (Bug #9277) innobase/trx/trx0trx.c: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql() (Bug #9277) --- innobase/include/trx0trx.h | 6 ++++++ innobase/trx/trx0trx.c | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 3be16e8f46d..4c93f25009f 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -346,6 +346,12 @@ struct trx_struct{ in MySQL's binlog write, we will flush the log to disk later in a separate call */ + ibool must_flush_log_later;/* this flag is set to TRUE in + trx_commit_off_kernel() if + flush_log_later was TRUE, and there + were modifications by the transaction; + in that case we must flush the log + in trx_commit_complete_for_mysql() */ dulint commit_lsn; /* lsn at the time of the commit */ ibool dict_operation; /* TRUE if the trx is used to create a table, create an index, or drop a diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 576827966ab..e2a24c2f63c 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -96,6 +96,7 @@ trx_create( trx->check_unique_secondary = TRUE; trx->flush_log_later = FALSE; + trx->must_flush_log_later = FALSE; trx->dict_operation = FALSE; @@ -634,6 +635,8 @@ trx_commit_off_kernel( #endif /* UNIV_SYNC_DEBUG */ rseg = trx->rseg; + + trx->must_flush_log_later = FALSE; if (trx->insert_undo != NULL || trx->update_undo != NULL) { @@ -798,6 +801,7 @@ trx_commit_off_kernel( if (trx->flush_log_later) { /* Do nothing yet */ + trx->must_flush_log_later = TRUE; } else if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { @@ -1516,7 +1520,9 @@ trx_commit_complete_for_mysql( trx->op_info = (char*)"flushing log"; - if (srv_flush_log_at_trx_commit == 0) { + if (!trx->must_flush_log_later) { + /* Do nothing */ + } if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { @@ -1538,6 +1544,8 @@ trx_commit_complete_for_mysql( ut_error; } + trx->must_flush_log_later = FALSE; + trx->op_info = (char*)""; return(0); From 6d0d2c7e1d942f95b4f29645ef5007c43da56f79 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 22:21:55 +0200 Subject: [PATCH 08/16] trx0trx.c: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql() (Bug #9277) innobase/trx/trx0trx.c: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql() (Bug #9277) --- innobase/trx/trx0trx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 8f409034df0..13575a3cedd 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -96,6 +96,7 @@ trx_create( trx->check_unique_secondary = TRUE; trx->flush_log_later = FALSE; + trx->must_flush_log_later = FALSE; trx->dict_operation = FALSE; @@ -654,6 +655,8 @@ trx_commit_off_kernel( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ + trx->must_flush_log_later = FALSE; + rseg = trx->rseg; if (trx->insert_undo != NULL || trx->update_undo != NULL) { @@ -821,6 +824,7 @@ trx_commit_off_kernel( if (trx->flush_log_later) { /* Do nothing yet */ + trx->must_flush_log_later = TRUE; } else if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { @@ -1539,7 +1543,9 @@ trx_commit_complete_for_mysql( trx->op_info = "flushing log"; - if (srv_flush_log_at_trx_commit == 0) { + if (!trx->must_flush_log_later) { + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { @@ -1560,6 +1566,8 @@ trx_commit_complete_for_mysql( } else { ut_error; } + + trx->must_flush_log_later = FALSE; trx->op_info = ""; From 802c41e04d0b4bb193abfff1b7084d3a6c971df6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 23:41:28 +0200 Subject: [PATCH 09/16] Cleanups during review of code Fixed newly introduced bug in rollup client/mysqldump.c: Safer buffer allocation Removed wrong assert mysql-test/r/olap.result: more tests mysql-test/t/olap.test: more tests sql/handler.cc: Simple cleanup Fixed wrong check for next digit (wrong debug output) sql/item.cc: Replace shrink_to_length() with mark_as_const() as the former allowed one to do changes to the string sql/item_sum.cc: Change reference to pointer Trivial optimzation of testing 'allways_null' sql/mysqld.cc: Proper indentation of comment sql/sql_select.cc: Fixed newly introduced bug in rollup sql/sql_string.h: Remove not needed 'shrink_to_length()' Added 'mark_as_const()' to be used when one want to ensure that a string is not changed --- client/mysqldump.c | 5 ++--- mysql-test/r/olap.result | 45 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/olap.test | 7 +++++++ sql/handler.cc | 14 ++++++++----- sql/item.cc | 14 ++----------- sql/item_sum.cc | 18 +++++++--------- sql/mysqld.cc | 7 ++++--- sql/sql_select.cc | 16 +++++++------- sql/sql_string.h | 5 +---- 9 files changed, 86 insertions(+), 45 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 46337c99732..867aa86c1fc 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1093,7 +1093,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, number of fields in table, 0 if error */ -static uint getTableStructure(char *table, char* db) +static uint getTableStructure(char *table, char *db) { MYSQL_RES *tableRes; MYSQL_ROW row; @@ -1396,10 +1396,9 @@ static uint getTableStructure(char *table, char* db) /* Get MySQL specific create options */ if (create_options) { - char show_name_buff[FN_REFLEN]; + char show_name_buff[NAME_LEN*2+2+24]; /* Check memory for quote_for_like() */ - DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff)); my_snprintf(buff, sizeof(buff), "show table status like %s", quote_for_like(table, show_name_buff)); diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 4863cb5b75e..91e52841c3b 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -378,6 +378,51 @@ a sum(b) 2 6 4 4 NULL 14 +SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +b a sum(b) +4 1 4 +NULL 1 4 +1 2 2 +2 2 4 +NULL 2 6 +1 4 4 +NULL 4 4 +NULL NULL 14 +SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +b a sum(b) +4 1 4 +NULL 1 4 +1 2 2 +2 2 4 +NULL 2 6 +1 4 4 +NULL 4 4 +NULL NULL 14 +ALTER TABLE t1 ADD COLUMN c INT; +SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +a b sum(c) +1 4 NULL +1 4 NULL +1 NULL NULL +2 1 NULL +2 1 NULL +2 2 NULL +2 2 NULL +2 NULL NULL +4 1 NULL +4 1 NULL +4 NULL NULL +NULL NULL NULL +SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +a b sum(c) +1 4 NULL +1 NULL NULL +2 1 NULL +2 2 NULL +2 NULL NULL +4 1 NULL +4 NULL NULL +NULL NULL NULL DROP TABLE t1; CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 3aac0f45ead..6e83968a506 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -153,6 +153,13 @@ SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; + +ALTER TABLE t1 ADD COLUMN c INT; +SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; + DROP TABLE t1; # diff --git a/sql/handler.cc b/sql/handler.cc index df0d7704163..98fc2be2f8a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -762,14 +762,13 @@ static char* xid_to_str(char *buf, XID *xid) for (i=0; i < xid->gtrid_length+xid->bqual_length; i++) { uchar c=(uchar)xid->data[i]; - bool is_next_dig; + /* is_next_dig is set if next character is a number */ + bool is_next_dig= FALSE; if (i < XIDDATASIZE) { - char ch=xid->data[i+1]; - is_next_dig=(c >= '0' && c <='9'); + char ch= xid->data[i+1]; + is_next_dig= (ch >= '0' && ch <='9'); } - else - is_next_dig=FALSE; if (i == xid->gtrid_length) { *s++='\''; @@ -782,6 +781,11 @@ static char* xid_to_str(char *buf, XID *xid) if (c < 32 || c > 126) { *s++='\\'; + /* + If next character is a number, write current character with + 3 octal numbers to ensure that the next number is not seen + as part of the octal number + */ if (c > 077 || is_next_dig) *s++=_dig_vec_lower[c >> 6]; if (c > 007 || is_next_dig) diff --git a/sql/item.cc b/sql/item.cc index 64fc2696f1f..91113db175e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -586,18 +586,8 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); - /* - The above line executes str_value.realloc() internally, - which alligns Alloced_length using ALLIGN_SIZE. - In the case of Item_string::str_value we don't want - Alloced_length to be longer than str_length. - Otherwise, some functions like Item_func_concat::val_str() - try to reuse str_value as a buffer for concatenation result - for optimization purposes, so our string constant become - corrupted. See bug#8785 for more details. - Let's shrink Alloced_length to str_length to avoid this problem. - */ - conv->str_value.shrink_to_length(); + /* Ensure that no one is going to change the result string */ + conv->str_value.mark_as_const(); return conv; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4b7415b6829..0676632d477 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2671,11 +2671,11 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), TABLE *table= item->table; char *record= (char*) table->record[0] + table->s->null_bytes; String tmp(table->record[1], table->s->reclength, default_charset_info), tmp2; - String &result= item->result; + String *result= &item->result; Item **arg= item->args, **arg_end= item->args + item->arg_count_field; - if (result.length()) - result.append(*item->separator); + if (result->length()) + result->append(*item->separator); tmp.length(0); @@ -2702,14 +2702,14 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), else res= (*arg)->val_str(&tmp); if (res) - result.append(*res); + result->append(*res); } /* stop if length of result more than max_length */ - if (result.length() > item->max_length) + if (result->length() > item->max_length) { item->count_cut_values++; - result.length(item->max_length); + result->length(item->max_length); item->warning_for_row= TRUE; return 1; } @@ -2910,8 +2910,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) MYF(0)); return TRUE; } - if (!args) /* allocation in constructor may fail */ - return TRUE; thd->allow_sum_func= 0; maybe_null= 0; @@ -2972,12 +2970,10 @@ bool Item_func_group_concat::setup(THD *thd) if (item->null_value) { always_null= 1; - break; + DBUG_RETURN(FALSE); } } } - if (always_null) - DBUG_RETURN(FALSE); List all_fields(list); /* diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6747b79703b..ecaa7ace841 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3310,9 +3310,10 @@ default_service_handling(char **argv, int main(int argc, char **argv) { - /* When several instances are running on the same machine, we - need to have an unique named hEventShudown through the - application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 + /* + When several instances are running on the same machine, we + need to have an unique named hEventShudown through the + application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 */ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name, "MySQLShutdown"), 10); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1e05400e88e..f8caabaead4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10145,20 +10145,18 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), join->sum_funcs_end[send_group_parts]); if (join->having && join->having->val_int() == 0) error= -1; - else if ((error=table->file->write_row(table->record[0]))) + else if ((error= table->file->write_row(table->record[0]))) { if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, error, 0)) DBUG_RETURN(-1); } - if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + if (join->rollup.state != ROLLUP::STATE_NONE) { if (join->rollup_write_data((uint) (idx+1), table)) - error= 1; + DBUG_RETURN(-1); } - if (error > 0) - DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -12685,17 +12683,21 @@ bool JOIN::rollup_make_fields(List &fields_arg, List &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group, i-- ; + for (group_tmp= start_group, i= pos ; group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { + Item_null_result *null_item; /* This is an element that is used by the GROUP BY and should be set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - Item_null_result *null_item= rollup.null_items[i]; + null_item= rollup.null_items[i]; + DBUG_ASSERT(null_item->result_field == 0 || + null_item->result_field == + ((Item_field *) item)->result_field); null_item->result_field= ((Item_field *) item)->result_field; item= null_item; break; diff --git a/sql/sql_string.h b/sql/sql_string.h index fc1e9f171b6..7ece9885040 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -84,6 +84,7 @@ public: inline char& operator [] (uint32 i) const { return Ptr[i]; } inline void length(uint32 len) { str_length=len ; } inline bool is_empty() { return (str_length == 0); } + inline void mark_as_const() { Alloced_length= 0;} inline const char *ptr() const { return Ptr; } inline char *c_ptr() { @@ -205,10 +206,6 @@ public: } } } - inline void shrink_to_length() - { - Alloced_length= str_length; - } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { From ddfdd6aa3b55ccca8eeb7f48857589c9d1ca6db2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 02:04:14 +0300 Subject: [PATCH 10/16] Fix for AIX compilation failure: sacred knowledge of my_global.h nature (it should be included before any other include) was hidden from me. server-tools/instance-manager/commands.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/commands.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/factory.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/guardian.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/guardian.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/instance.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/instance.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/instance_map.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/instance_map.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/instance_options.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/log.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/manager.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/messages.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/messages.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/mysql_connection.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/mysqlmanager.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/options.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/parse.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/parse_output.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/protocol.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/protocol.h: Fix for AIX compilation failure & cleanup server-tools/instance-manager/thread_registry.cc: Fix for AIX compilation failure & cleanup server-tools/instance-manager/user_map.h: Fix for AIX compilation failure & cleanup --- server-tools/instance-manager/commands.cc | 7 +++++-- server-tools/instance-manager/commands.h | 2 +- server-tools/instance-manager/factory.cc | 5 ----- server-tools/instance-manager/guardian.cc | 2 ++ server-tools/instance-manager/guardian.h | 3 ++- server-tools/instance-manager/instance.cc | 8 ++++---- server-tools/instance-manager/instance.h | 2 -- server-tools/instance-manager/instance_map.cc | 3 ++- server-tools/instance-manager/instance_map.h | 7 ++++--- .../instance-manager/instance_options.cc | 2 ++ server-tools/instance-manager/log.cc | 4 +++- server-tools/instance-manager/manager.cc | 2 +- server-tools/instance-manager/messages.cc | 7 +++++-- server-tools/instance-manager/messages.h | 3 --- .../instance-manager/mysql_connection.cc | 17 ++++++++++------- server-tools/instance-manager/mysqlmanager.cc | 3 ++- server-tools/instance-manager/options.cc | 5 ++--- server-tools/instance-manager/parse.cc | 1 + server-tools/instance-manager/parse_output.cc | 2 +- server-tools/instance-manager/protocol.cc | 8 ++++---- server-tools/instance-manager/protocol.h | 1 + .../instance-manager/thread_registry.cc | 3 ++- server-tools/instance-manager/user_map.h | 3 ++- 23 files changed, 56 insertions(+), 44 deletions(-) diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 9831ad3a891..426f0cc40b2 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -14,14 +14,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "command.h" #include "commands.h" -#include "instance.h" + #include "instance_map.h" #include "messages.h" +#include "mysqld_error.h" +#include "mysql_manager_error.h" #include "protocol.h" #include "buffer.h" + #include +#include /* implementation for Show_instances: */ diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index cd13bf09549..bab67f9c6b4 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -16,8 +16,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "command.h" #include "instance.h" -#include "my_global.h" /* Print all instances of this instance manager. diff --git a/server-tools/instance-manager/factory.cc b/server-tools/instance-manager/factory.cc index cde5d0564aa..538d9353983 100644 --- a/server-tools/instance-manager/factory.cc +++ b/server-tools/instance-manager/factory.cc @@ -15,11 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "factory.h" -#include "my_global.h" - -#include -#include - Show_instances *Command_factory::new_Show_instances() { diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 4fbfaf2672d..5d89f167f2f 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -20,10 +20,12 @@ #endif #include "guardian.h" + #include "instance_map.h" #include "instance.h" #include "mysql_manager_error.h" #include "log.h" + #include #include #include diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h index e43b5d565d7..502dc86b2ae 100644 --- a/server-tools/instance-manager/guardian.h +++ b/server-tools/instance-manager/guardian.h @@ -17,9 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include "thread_registry.h" + #include #include -#include "thread_registry.h" #ifdef __GNUC__ #pragma interface diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 97282f3f800..f5effe68c64 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -19,16 +19,16 @@ #endif #include "instance.h" + #include "mysql_manager_error.h" #include "log.h" #include "instance_map.h" #include "priv.h" -#include -#include -#include #include - +#include +#include +#include C_MODE_START diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index c141ff7b30d..14ef5cfcfb9 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -17,8 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include -#include #include "instance_options.h" #ifdef __GNUC__ diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index d19d42662e5..3e76c24a9a1 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -19,10 +19,11 @@ #endif #include "instance_map.h" + #include "buffer.h" #include "instance.h" + #include -#include #include #include diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 8d8ea33cf5d..46247c82a16 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -17,6 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include + +#include "protocol.h" +#include "guardian.h" + #include #include @@ -24,9 +28,6 @@ #pragma interface #endif -#include "protocol.h" -#include "guardian.h" - class Instance; extern int load_all_groups(char ***groups, const char *filename); extern void free_groups(char **groups); diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index e1b81bc93b1..0d602f88ad2 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -19,8 +19,10 @@ #endif #include "instance_options.h" + #include "parse_output.h" #include "buffer.h" + #include #include #include diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index dbcea3f9c3d..5491b4e70e9 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -14,8 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "log.h" #include + +#include "log.h" + #include #include #include diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 8629c5e9d9c..fd8673c4d66 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -14,6 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "manager.h" #include "priv.h" @@ -25,7 +26,6 @@ #include "log.h" #include "guardian.h" -#include #include #include #include diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc index e3c2423a47e..d044c0f65db 100644 --- a/server-tools/instance-manager/messages.cc +++ b/server-tools/instance-manager/messages.cc @@ -13,11 +13,14 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "messages.h" #include -#include +#include "messages.h" +#include "mysqld_error.h" +#include "mysql_manager_error.h" + +#include #include diff --git a/server-tools/instance-manager/messages.h b/server-tools/instance-manager/messages.h index 4cc15b5efe4..b771efe5e13 100644 --- a/server-tools/instance-manager/messages.h +++ b/server-tools/instance-manager/messages.h @@ -16,9 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysqld_error.h" -#include "mysql_manager_error.h" - const char *message(unsigned sql_errno); const char *errno_to_sqlstate(unsigned sql_errno); diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 7947de70459..215dbe51b58 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -19,14 +19,10 @@ #endif #include "mysql_connection.h" + #include "priv.h" - -#include -#include -#include -#include -#include - +#include "mysql_manager_error.h" +#include "mysqld_error.h" #include "thread_registry.h" #include "log.h" #include "user_map.h" @@ -36,6 +32,13 @@ #include "factory.h" #include "parse.h" +#include +#include +#include +#include +#include + + Command *parse_command(Command_factory * factory, const char *text); Mysql_connection_thread_args::Mysql_connection_thread_args( diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index e1d267b492e..262686c3fab 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -14,11 +14,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "manager.h" + #include "options.h" #include "log.h" -#include #include #include #include diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 9e4205b1407..4b5ec27f302 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -20,14 +20,13 @@ #include "options.h" -#include +#include "priv.h" + #include #include #include #include -#include "priv.h" - #define QUOTE2(x) #x #define QUOTE(x) QUOTE2(x) diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index 4c897ddf933..d3fb10b7c94 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "parse.h" + #include enum Token diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 6fee0797395..77fa40ca352 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -14,10 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "parse.h" #include -#include #include #include diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc index 60cd0e8714f..9c8975a78be 100644 --- a/server-tools/instance-manager/protocol.cc +++ b/server-tools/instance-manager/protocol.cc @@ -14,13 +14,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include +#include "protocol.h" + +#include "messages.h" + #include #include -#include "messages.h" -#include "protocol.h" static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h index 1102f95ff8f..b7b18b4b76c 100644 --- a/server-tools/instance-manager/protocol.h +++ b/server-tools/instance-manager/protocol.h @@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "buffer.h" + #include typedef struct field { diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index bf01aa6d7b2..16821df4146 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -20,10 +20,11 @@ #include "thread_registry.h" +#include "log.h" + #include #include #include -#include "log.h" /* Kick-off signal handler */ diff --git a/server-tools/instance-manager/user_map.h b/server-tools/instance-manager/user_map.h index dcd2fd1494d..4c86edd93d9 100644 --- a/server-tools/instance-manager/user_map.h +++ b/server-tools/instance-manager/user_map.h @@ -17,10 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __GNUC__ -#pragma interface +#pragma interface #endif #include + #include #include From ac46bf77aecd84eae40400afd5ffb79e93ab4b24 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 00:26:12 +0100 Subject: [PATCH 11/16] Last part of WL#1062: better replication of timezones: no more use of SET ONE_SHOT; storing tz info directly in event (if this info is needed), it's now allowed to have different global tz on master and slave. client/mysqlbinlog.cc: we need MAX_TIME_ZONE_NAME_LENGTH when processing log_event.h, and it's declared in mysql_priv.h mysql-test/r/rpl_timezone.result: result update mysql-test/t/rpl_timezone-slave.opt: Now that we can have different global value of timezone on master and slave, let's test it. mysql-test/t/rpl_timezone.test: Tests of the new replication of timezones: checking the output of mysqlbinlog, replication of CONVERT_TZ(). sql/ha_innodb.cc: No very fast shutdown on Netware (anyway it's disabled on all platforms, but this is so that we don't forget to keep it disabled on Netware in the future). sql/log.cc: No more need to write SET ONE_SHOT to binlog for character set and timezone (as we store this info directly nin the Query_log_event now). sql/log_event.cc: Exclude ::write() methods if MYSQL_CLIENT. Storing timezone info in the Query_log_event in master. Re-reading it in slave. Small code cleanups. I plan to not store the end 0 of catalog in binlog events soon. sql/log_event.h: replication of time zones: a place for tz info in Query_log_event, in LAST_EVENT_INFO. Plus if we are compiling a client, we don't need the ::write() methods, so keeping them out (of mysqlbinlog.cc; keeping them in, resulted in problem that mysqlbinlog does not know Timezone structure). sql/mysql_priv.h: moving this define from tztime.h (tztime.h has things which are too much for a client like mysqlbinlog). sql/set_var.cc: It's now allowed to change global value of charset or timezone even if using binlogging or if being a slave. Making CONVERT_TZ(,,@@session.time_zone) replicate. sql/set_var.h: these ::check()s are not needed anymore (changing global charset or timezone is now allowed even if binlogging or slave) sql/slave.cc: No more need to check for same global timezone if master is 5.x (ok, strictly speaking if it is > 5.0.3 but this is alpha). sql/slave.h: a function to wrap settings of charset to default. sql/tztime.cc: Adaptation of my_tz_find() to the case where it's not called from inside a query (i.e. cannot join its tz tables to the query's ones): this variant opens the tz tables itself, reads from them, and closes them. This is presently only used by the slave SQL thread (when it sets the tz before executing a query). sql/tztime.h: declaration of new function, plus moving symbol to mysql_priv.h for easier usage in mysqlbinlog (Dmitri, pardon me). BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + client/mysqlbinlog.cc | 2 +- mysql-test/r/rpl_timezone.result | 65 ++++++++--- mysql-test/t/rpl_timezone-slave.opt | 2 +- mysql-test/t/rpl_timezone.test | 34 ++++-- sql/ha_innodb.cc | 4 + sql/log.cc | 51 --------- sql/log_event.cc | 165 +++++++++++++++++++--------- sql/log_event.h | 45 +++++++- sql/mysql_priv.h | 6 + sql/set_var.cc | 56 ++-------- sql/set_var.h | 6 - sql/slave.cc | 21 +++- sql/slave.h | 1 + sql/tztime.cc | 56 +++++++++- sql/tztime.h | 7 +- 16 files changed, 322 insertions(+), 200 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index eff53f4a789..46814ec8517 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -48,6 +48,7 @@ dlenev@build.mysql.com dlenev@jabberwock.localdomain dlenev@mysql.com ejonore@mc03.ndb.mysql.com +gbichot@production.mysql.com gbichot@quadita2.mysql.com georg@beethoven.local georg@beethoven.site diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c296447def9..59c90f59e8e 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -33,9 +33,9 @@ #undef MYSQL_SERVER #include "client_priv.h" #include -#include "log_event.h" /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ #include "mysql_priv.h" +#include "log_event.h" #define BIN_LOG_HEADER_SIZE 4 #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result index cd2c4d099be..8975333d1db 100644 --- a/mysql-test/r/rpl_timezone.result +++ b/mysql-test/r/rpl_timezone.result @@ -4,21 +4,31 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +set timestamp=100000000; create table t1 (t timestamp); create table t2 (t char(32)); select @@time_zone; @@time_zone +Japan +select @@time_zone; +@@time_zone Europe/Moscow +insert into t1 values ('20050101000000'), ('20050611093902'); set time_zone='UTC'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; t +2004-12-31 21:00:00 +2005-06-11 05:39:02 2004-01-01 00:00:00 2004-06-11 09:39:02 +set time_zone='UTC'; select * from t1; t -2004-01-01 03:00:00 -2004-06-11 13:39:02 +2004-12-31 21:00:00 +2005-06-11 05:39:02 +2004-01-01 00:00:00 +2004-06-11 09:39:02 delete from t1; set time_zone='Europe/Moscow'; insert into t1 values ('20040101000000'), ('20040611093902'); @@ -26,19 +36,35 @@ select * from t1; t 2004-01-01 00:00:00 2004-06-11 09:39:02 +set time_zone='Europe/Moscow'; select * from t1; t 2004-01-01 00:00:00 2004-06-11 09:39:02 -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4 -master-bin.000001 # Query 1 # use `test`; create table t1 (t timestamp) -master-bin.000001 # Query 1 # use `test`; create table t2 (t char(32)) -master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT TIME_ZONE='UTC' -master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') -master-bin.000001 # Query 1 # use `test`; delete from t1 -master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +ROLLBACK; +use test; +SET TIMESTAMP=100000000; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; +SET @@session.sql_mode=0; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8; +create table t1 (t timestamp); +SET TIMESTAMP=100000000; +create table t2 (t char(32)); +SET TIMESTAMP=100000000; +SET @@session.time_zone='Europe/Moscow'; +insert into t1 values ('20050101000000'), ('20050611093902'); +SET TIMESTAMP=100000000; +SET @@session.time_zone='UTC'; +insert into t1 values ('20040101000000'), ('20040611093902'); +SET TIMESTAMP=100000000; +delete from t1; +SET TIMESTAMP=100000000; +SET @@session.time_zone='Europe/Moscow'; +insert into t1 values ('20040101000000'), ('20040611093902'); +ROLLBACK; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; set time_zone='MET'; insert into t2 (select t from t1); select * from t1; @@ -52,10 +78,6 @@ t delete from t2; set timestamp=1000072000; insert into t2 values (current_timestamp), (current_date), (current_time); -set timestamp=1000072000; -select current_timestamp, current_date, current_time; -current_timestamp current_date current_time -2001-09-10 01:46:40 2001-09-10 01:46:40 select * from t2; t 2001-09-09 23:46:40 @@ -73,5 +95,16 @@ t 2001-09-09 03:46:40 1000000000 set global time_zone='MET'; -ERROR HY000: Binary logging and replication forbid changing the global server time zone +delete from t2; +set time_zone='UTC'; +insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); +insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); +select * from t2; +t +2003-12-31 23:00:00 +2005-01-01 08:00:00 +select * from t2; +t +2003-12-31 23:00:00 +2005-01-01 08:00:00 drop table t1, t2; diff --git a/mysql-test/t/rpl_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt index 8e43bfbbb7e..191182c329c 100644 --- a/mysql-test/t/rpl_timezone-slave.opt +++ b/mysql-test/t/rpl_timezone-slave.opt @@ -1 +1 @@ ---default-time-zone=Europe/Moscow +--default-time-zone=Japan diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test index 3c180ca8849..a49cdd0acd2 100644 --- a/mysql-test/t/rpl_timezone.test +++ b/mysql-test/t/rpl_timezone.test @@ -3,21 +3,25 @@ source include/master-slave.inc; # Some preparations let $VERSION=`select version()`; +set timestamp=100000000; # for fixed output of mysqlbinlog create table t1 (t timestamp); create table t2 (t char(32)); +connection slave; +select @@time_zone; + # # Let us check how well replication works when we are saving datetime # value in TIMESTAMP field. # connection master; select @@time_zone; +insert into t1 values ('20050101000000'), ('20050611093902'); set time_zone='UTC'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; -# On slave we still in 'Europe/Moscow' so we should see equivalent but -# textually different values. sync_slave_with_master; +set time_zone='UTC'; select * from t1; # Let us check also that setting of time_zone back to default also works @@ -28,12 +32,11 @@ set time_zone='Europe/Moscow'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; sync_slave_with_master; +set time_zone='Europe/Moscow'; select * from t1; connection master; -# We should not see SET ONE_SHOT time_zone before second insert ---replace_result $VERSION VERSION ---replace_column 2 # 5 # -show binlog events; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 # # Now let us check how well we replicate statments reading TIMESTAMP fields @@ -54,10 +57,6 @@ delete from t2; set timestamp=1000072000; insert into t2 values (current_timestamp), (current_date), (current_time); sync_slave_with_master; -# Values in ouput of these to queries should differ because we are in -# in 'MET' on master and in 'Europe/Moscow on slave... -set timestamp=1000072000; -select current_timestamp, current_date, current_time; select * from t2; # @@ -73,13 +72,24 @@ sync_slave_with_master; select * from t2; # -# Let us check that we are not allowing to set global time_zone with +# Let us check that we are allowing to set global time_zone with # replication # connection master; ---error 1387 set global time_zone='MET'; +# +# Let us see if CONVERT_TZ(@@time_zone) replicates +# +delete from t2; +set time_zone='UTC'; +insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); +insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); +select * from t2; +sync_slave_with_master; +select * from t2; + # Clean up +connection master; drop table t1, t2; sync_slave_with_master; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 870ad1af52b..24f1579544b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1307,6 +1307,9 @@ innobase_end(void) } #endif if (innodb_inited) { + +#ifndef __NETWARE__ /* NetWare can't close unclosed files, kill remaining + threads, etc, so we disable the very fast shutdown */ if (innobase_very_fast_shutdown) { srv_very_fast_shutdown = TRUE; fprintf(stderr, @@ -1314,6 +1317,7 @@ innobase_end(void) "InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n" "InnoDB: InnoDB will do a crash recovery!\n"); } +#endif innodb_inited = 0; if (innobase_shutdown_for_mysql() != DB_SUCCESS) { diff --git a/sql/log.cc b/sql/log.cc index 43786990797..0c1d6836cce 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info) if (thd) { -#if MYSQL_VERSION_ID < 50003 - /* - To make replication of charsets working in 4.1 we are writing values - of charset related variables before every statement in the binlog, - if values of those variables differ from global server-wide defaults. - We are using SET ONE_SHOT command so that the charset vars get reset - to default after the first non-SET statement. - In the next 5.0 this won't be needed as we will use the new binlog - format to store charset info. - */ - if ((thd->variables.character_set_client->number != - global_system_variables.collation_server->number) || - (thd->variables.character_set_client->number != - thd->variables.collation_connection->number) || - (thd->variables.collation_server->number != - thd->variables.collation_connection->number)) - { - char buf[200]; - int written= my_snprintf(buf, sizeof(buf)-1, - "SET ONE_SHOT CHARACTER_SET_CLIENT=%u,\ -COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", - (uint) thd->variables.character_set_client->number, - (uint) thd->variables.collation_connection->number, - (uint) thd->variables.collation_database->number, - (uint) thd->variables.collation_server->number); - Query_log_event e(thd, buf, written, 0, FALSE); - if (e.write(file)) - goto err; - } -#endif - /* - We use the same ONE_SHOT trick for making replication of time zones - working in 4.1. Again in 5.0 we have better means for doing this. - - TODO: we should do like we now do with charsets (no more ONE_SHOT; - logging in each event in a compact format). Dmitri says we can do: - if (time_zone_used) write the timezone to binlog (in a format to be - defined). - */ - if (thd->time_zone_used && - thd->variables.time_zone != global_system_variables.time_zone) - { - char buf[MAX_TIME_ZONE_NAME_LENGTH + 26]; - char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='", - thd->variables.time_zone->get_name()->ptr(), - "'", NullS); - Query_log_event e(thd, buf, buf_end - buf, 0, FALSE); - if (e.write(file)) - goto err; - } - if (thd->last_insert_id_used) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, diff --git a/sql/log_event.cc b/sql/log_event.cc index ba018e859c1..666c2427ac5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -506,8 +506,6 @@ void Log_event::init_show_field_list(List* field_list) field_list->push_back(new Item_empty_string("Info", 20)); } -#endif /* !MYSQL_CLIENT */ - /* Log_event::write() @@ -592,7 +590,6 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) */ -#ifndef MYSQL_CLIENT int Log_event::read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock) { @@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol) } #endif +#ifndef MYSQL_CLIENT /* Query_log_event::write() @@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file) 1+8+ // code of sql_mode and sql_mode 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog 1+4+ // code of autoinc and the 2 autoinc variables - 1+6 // code of charset and charset + 1+6+ // code of charset and charset + 1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name ], *start, *start_of_status; ulong event_length; @@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file) start_of_status= start= buf+QUERY_HEADER_LEN; if (flags2_inited) { - *(start++)= Q_FLAGS2_CODE; + *start++= Q_FLAGS2_CODE; int4store(start, flags2); start+= 4; } if (sql_mode_inited) { - *(start++)= Q_SQL_MODE_CODE; + *start++= Q_SQL_MODE_CODE; int8store(start, (ulonglong)sql_mode); start+= 8; } - if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events) + if (catalog_len) // i.e. "catalog inited" (false for 4.0 events) { - *(start++)= Q_CATALOG_CODE; - *(start++)= (uchar) catalog_len; + *start++= Q_CATALOG_CODE; + *start++= (uchar) catalog_len; bmove(start, catalog, catalog_len); start+= catalog_len; /* @@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file) } if (charset_inited) { - *(start++)= Q_CHARSET_CODE; + *start++= Q_CHARSET_CODE; memcpy(start, charset, 6); start+= 6; } + if (time_zone_len) + { + /* In the TZ sys table, column Name is of length 64 so this should be ok */ + DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); + *start++= Q_TIME_ZONE_CODE; + *start++= time_zone_len; + memcpy(start, time_zone_str, time_zone_len); + start+= time_zone_len; + } /* Here there could be code like if (command-line-option-which-says-"log_this_variable" && inited) { - *(start++)= Q_THIS_VARIABLE_CODE; + *start++= Q_THIS_VARIABLE_CODE; int4store(start, this_variable); start+= 4; } @@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file) /* Query_log_event::Query_log_event() */ - -#ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool suppress_use) @@ -1150,6 +1156,18 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, int2store(charset, thd_arg->variables.character_set_client->number); int2store(charset+2, thd_arg->variables.collation_connection->number); int2store(charset+4, thd_arg->variables.collation_server->number); + if (thd_arg->time_zone_used) + { + /* + Note that our event becomes dependent on the Time_zone object + representing the time zone. Fortunately such objects are never deleted + or changed during mysqld's lifetime. + */ + time_zone_len= thd_arg->variables.time_zone->get_name()->length(); + time_zone_str= thd_arg->variables.time_zone->get_name()->ptr(); + } + else + time_zone_len= 0; DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode)); } #endif /* MYSQL_CLIENT */ @@ -1163,15 +1181,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, Query_log_event::Query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event, Log_event_type event_type) - :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS), + :Log_event(buf, description_event), data_buf(0), query(NullS), db(NullS), catalog_len(0), status_vars_len(0), flags2_inited(0), sql_mode_inited(0), charset_inited(0), - auto_increment_increment(1), auto_increment_offset(1) + auto_increment_increment(1), auto_increment_offset(1), + time_zone_len(0) { ulong data_len; uint32 tmp; uint8 common_header_len, post_header_len; - const char *start, *end; + char *start; + const char *end; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); common_header_len= description_event->common_header_len; @@ -1191,7 +1211,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; + db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -1217,7 +1237,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, /* variable-part: the status vars; only in MySQL 5.0 */ start= (char*) (buf+post_header_len); - end= (char*) (start+status_vars_len); + end= (const char*) (start+status_vars_len); for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;) { switch (*pos++) { @@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, break; } case Q_CATALOG_CODE: - catalog_len= *pos; - if (catalog_len) + if ((catalog_len= *pos)) catalog= (char*) pos+1; // Will be copied later pos+= catalog_len+2; break; @@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, pos+= 6; break; } + case Q_TIME_ZONE_CODE: + { + if ((time_zone_len= *pos)) + time_zone_str= (char *)(pos+1); + pos+= time_zone_len+1; + break; + } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -1265,24 +1291,29 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } } - /* A 2nd variable part; this is common to all versions */ - - if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME)))) + if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + + time_zone_len + 1 + + data_len + 1, MYF(MY_WME)))) DBUG_VOID_RETURN; - if (catalog) // If catalog is given + if (catalog_len) // If catalog is given { - memcpy((char*) start, catalog, catalog_len+1); // Copy name and end \0 + memcpy(start, catalog, catalog_len+1); // Copy name and end \0 catalog= start; start+= catalog_len+1; } + if (time_zone_len) + { + memcpy(start, time_zone_str, time_zone_len); + time_zone_str= start; + start+= time_zone_len; + *start++= 0; + } + /* A 2nd variable part; this is common to all versions */ memcpy((char*) start, end, data_len); // Copy db and query - ((char*) start)[data_len]= '\0'; // End query with \0 (For safetly) + start[data_len]= '\0'; // End query with \0 (For safetly) db= start; query= start + db_len + 1; q_len= data_len - db_len -1; - /* This is used to detect wrong parsing. Could be removed in the future. */ - DBUG_PRINT("info", ("catalog: '%s' len: %u db: '%s' len: %u q_len: %lu", - catalog, (uint) catalog_len, db, (uint) db_len,q_len)); DBUG_VOID_RETURN; } @@ -1390,6 +1421,8 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, last_event_info->auto_increment_offset= auto_increment_offset; } + /* TODO: print the catalog when we feature SET CATALOG */ + if (likely(charset_inited)) { if (unlikely(!last_event_info->charset_inited)) /* first Query event */ @@ -1410,6 +1443,14 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, memcpy(last_event_info->charset, charset, 6); } } + if (time_zone_len) + { + if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1)) + { + fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str); + memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1); + } + } } @@ -1443,7 +1484,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query alloced block (see Query_log_event::exec_event()). Same for thd->db. Thank you. */ - thd->catalog= (char*) catalog; + thd->catalog= catalog_len ? (char *) catalog : (char *)""; thd->db_length= db_len; thd->db= (char*) rewrite_db(db, &thd->db_length); thd->variables.auto_increment_increment= auto_increment_increment; @@ -1513,20 +1554,28 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query get_charset(uint2korr(charset+4), MYF(MY_WME)))) { /* - We updated the thd->variables with nonsensical values (0), and the - thread is not guaranteed to terminate now (as it may be configured - to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next - statement we'll have a new charset info with it, so no problem to - have stored 0 in thd->variables. But we invalidate cached - charset to force a check next time (otherwise if next time - charset is unknown again we won't detect it). + We updated the thd->variables with nonsensical values (0). Let's + set them to something safe (i.e. which avoids crash), and we'll + stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to + ignore this error). */ - rli->cached_charset_invalidate(); + set_slave_thread_default_charset(thd, rli); goto compare_errors; } thd->update_charset(); // for the charset change to take effect } } + if (time_zone_len) + { + String tmp(time_zone_str, time_zone_len, &my_charset_bin); + if (!(thd->variables.time_zone= + my_tz_find_with_opening_tz_tables(thd, &tmp))) + { + my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr()); + thd->variables.time_zone= global_system_variables.time_zone; + goto compare_errors; + } + } /* Execute the query (note that we bypass dispatch_command()) */ mysql_parse(thd, thd->query, thd->query_length); @@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf, Start_log_event_v3::write() */ +#ifndef MYSQL_CLIENT bool Start_log_event_v3::write(IO_CACHE* file) { char buff[START_V3_HEADER_LEN]; @@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, (byte*) buff, sizeof(buff))); } +#endif /* @@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf, DBUG_VOID_RETURN; } - +#ifndef MYSQL_CLIENT bool Format_description_log_event::write(IO_CACHE* file) { /* @@ -1992,6 +2043,7 @@ bool Format_description_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, buff, sizeof(buff))); } +#endif /* SYNOPSIS @@ -2208,6 +2260,8 @@ void Load_log_event::pack_info(Protocol *protocol) #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ +#ifndef MYSQL_CLIENT + /* Load_log_event::write_data_header() */ @@ -2249,7 +2303,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file) Load_log_event::Load_log_event() */ -#ifndef MYSQL_CLIENT Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, const char *db_arg, const char *table_name_arg, List &fields_arg, @@ -2863,6 +2916,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, Rotate_log_event::write() */ +#ifndef MYSQL_CLIENT bool Rotate_log_event::write(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; @@ -2871,7 +2925,7 @@ bool Rotate_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); } - +#endif /* Rotate_log_event::exec_event() @@ -2929,17 +2983,10 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) master is 4.0 then the events are in the slave's format (conversion). */ set_slave_thread_options(thd); + set_slave_thread_default_charset(thd, rli); thd->variables.sql_mode= global_system_variables.sql_mode; thd->variables.auto_increment_increment= thd->variables.auto_increment_offset= 1; - thd->variables.character_set_client= - global_system_variables.character_set_client; - thd->variables.collation_connection= - global_system_variables.collation_connection; - thd->variables.collation_server= - global_system_variables.collation_server; - thd->update_charset(); - rli->cached_charset_invalidate(); } pthread_mutex_unlock(&rli->data_lock); pthread_cond_broadcast(&rli->data_cond); @@ -3001,6 +3048,7 @@ const char* Intvar_log_event::get_var_type_name() Intvar_log_event::write() */ +#ifndef MYSQL_CLIENT bool Intvar_log_event::write(IO_CACHE* file) { byte buf[9]; @@ -3009,6 +3057,7 @@ bool Intvar_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -3093,6 +3142,7 @@ Rand_log_event::Rand_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Rand_log_event::write(IO_CACHE* file) { byte buf[16]; @@ -3101,6 +3151,7 @@ bool Rand_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif #ifdef MYSQL_CLIENT @@ -3164,11 +3215,13 @@ Xid_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Xid_log_event::write(IO_CACHE* file) { return write_header(file, sizeof(xid)) || my_b_safe_write(file, (byte*) &xid, sizeof(xid)); } +#endif #ifdef MYSQL_CLIENT @@ -3302,6 +3355,7 @@ User_var_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool User_var_log_event::write(IO_CACHE* file) { char buf[UV_NAME_LEN_SIZE]; @@ -3361,6 +3415,7 @@ bool User_var_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*) buf1, buf1_length) || my_b_safe_write(file, (byte*) pos, val_len)); } +#endif /* @@ -3634,6 +3689,7 @@ int Slave_log_event::get_data_size() } +#ifndef MYSQL_CLIENT bool Slave_log_event::write(IO_CACHE* file) { ulong event_length= get_data_size(); @@ -3644,6 +3700,7 @@ bool Slave_log_event::write(IO_CACHE* file) return (write_header(file, event_length) || my_b_safe_write(file, (byte*) mem_pool, event_length)); } +#endif void Slave_log_event::init_from_mem_pool(int data_size) @@ -3770,7 +3827,6 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, sql_ex.force_new_format(); DBUG_VOID_RETURN; } -#endif /* !MYSQL_CLIENT */ /* @@ -3815,6 +3871,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file) return res; } +#endif /* !MYSQL_CLIENT */ /* Create_file_log_event ctor @@ -4042,6 +4099,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, Append_block_log_event::write() */ +#ifndef MYSQL_CLIENT bool Append_block_log_event::write(IO_CACHE* file) { byte buf[APPEND_BLOCK_HEADER_LEN]; @@ -4050,6 +4108,7 @@ bool Append_block_log_event::write(IO_CACHE* file) my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || my_b_safe_write(file, (byte*) block, block_len)); } +#endif /* @@ -4171,6 +4230,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len, Delete_file_log_event::write() */ +#ifndef MYSQL_CLIENT bool Delete_file_log_event::write(IO_CACHE* file) { byte buf[DELETE_FILE_HEADER_LEN]; @@ -4178,6 +4238,7 @@ bool Delete_file_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4265,6 +4326,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len, Execute_load_log_event::write() */ +#ifndef MYSQL_CLIENT bool Execute_load_log_event::write(IO_CACHE* file) { byte buf[EXEC_LOAD_HEADER_LEN]; @@ -4272,6 +4334,7 @@ bool Execute_load_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4475,6 +4538,7 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived() } +#ifndef MYSQL_CLIENT bool Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) { @@ -4485,6 +4549,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) *(buf + 4 + 4 + 4)= (char)dup_handling; return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); } +#endif #ifdef MYSQL_CLIENT diff --git a/sql/log_event.h b/sql/log_event.h index 43a801da851..72142db0aa7 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -237,6 +237,7 @@ struct sql_ex_info #define Q_CATALOG_CODE 2 #define Q_AUTO_INCREMENT 3 #define Q_CHARSET_CODE 4 +#define Q_TIME_ZONE_CODE 5 /* Intvar event post-header */ @@ -448,6 +449,7 @@ typedef struct st_last_event_info ulong auto_increment_increment, auto_increment_offset; bool charset_inited; char charset[6]; // 3 variables, each of them storable in 2 bytes + char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; st_last_event_info() :flags2_inited(0), sql_mode_inited(0), auto_increment_increment(1),auto_increment_offset(1), charset_inited(0) @@ -459,6 +461,7 @@ typedef struct st_last_event_info */ bzero(db, sizeof(db)); bzero(charset, sizeof(charset)); + bzero(time_zone_str, sizeof(time_zone_str)); } } LAST_EVENT_INFO; #endif @@ -583,6 +586,7 @@ public: my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); } +#ifndef MYSQL_CLIENT bool write_header(IO_CACHE* file, ulong data_length); virtual bool write(IO_CACHE* file) { @@ -590,13 +594,14 @@ public: write_data_header(file) || write_data_body(file)); } - virtual bool is_artificial_event() { return 0; } virtual bool write_data_header(IO_CACHE* file) { return 0; } virtual bool write_data_body(IO_CACHE* file __attribute__((unused))) { return 0; } +#endif virtual Log_event_type get_type_code() = 0; virtual bool is_valid() const = 0; + virtual bool is_artificial_event() { return 0; } inline bool get_cache_stmt() { return cache_stmt; } Log_event(const char* buf, const Format_description_log_event* description_event); virtual ~Log_event() { free_temp_buf();} @@ -672,7 +677,7 @@ public: concerned) from here. */ - int catalog_len; // <= 255 char; -1 means uninited + uint catalog_len; // <= 255 char; 0 means uninited /* We want to be able to store a variable number of N-bit status vars: @@ -714,6 +719,8 @@ public: ulong sql_mode; ulong auto_increment_increment, auto_increment_offset; char charset[6]; + uint time_zone_len; /* 0 means uninited */ + const char *time_zone_str; #ifndef MYSQL_CLIENT @@ -737,12 +744,13 @@ public: ~Query_log_event() { if (data_buf) - { my_free((gptr) data_buf, MYF(0)); - } } Log_event_type get_type_code() { return QUERY_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); + virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } +#endif bool is_valid() const { return query != 0; } /* @@ -751,7 +759,6 @@ public: */ virtual ulong get_post_header_size_for_derived() { return 0; } /* Writes derived event-specific part of post header. */ - virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } }; #ifdef HAVE_REPLICATION @@ -790,7 +797,9 @@ public: int get_data_size(); bool is_valid() const { return master_host != 0; } Log_event_type get_type_code() { return SLAVE_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; #endif /* HAVE_REPLICATION */ @@ -885,8 +894,10 @@ public: { return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); +#endif bool is_valid() const { return table_name != 0; } int get_data_size() { @@ -962,7 +973,9 @@ public: const Format_description_log_event* description_event); ~Start_log_event_v3() {} Log_event_type get_type_code() { return START_EVENT_V3;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } int get_data_size() { @@ -1004,7 +1017,9 @@ public: const Format_description_log_event* description_event); ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); } Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN : @@ -1054,7 +1069,9 @@ public: Log_event_type get_type_code() { return INTVAR_EVENT;} const char* get_var_type_name(); int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event ~Rand_log_event() {} Log_event_type get_type_code() { return RAND_EVENT;} int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event ~Xid_log_event() {} Log_event_type get_type_code() { return XID_EVENT;} int get_data_size() { return sizeof(xid); } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1169,7 +1190,9 @@ public: User_var_log_event(const char* buf, const Format_description_log_event* description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1239,7 +1262,9 @@ public: Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} bool is_valid() const { return new_log_ident != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; @@ -1299,6 +1324,7 @@ public: 4 + 1 + block_len); } bool is_valid() const { return inited_from_old || block != 0; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); /* @@ -1306,6 +1332,7 @@ public: write it as Load event - used on the slave */ bool write_base(IO_CACHE* file); +#endif }; @@ -1352,7 +1379,9 @@ public: Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;} int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;} bool is_valid() const { return block != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1386,7 +1415,9 @@ public: Log_event_type get_type_code() { return DELETE_FILE_EVENT;} int get_data_size() { return DELETE_FILE_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1419,7 +1450,9 @@ public: Log_event_type get_type_code() { return EXEC_LOAD_EVENT;} int get_data_size() { return EXEC_LOAD_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1507,7 +1540,9 @@ public: bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; } ulong get_post_header_size_for_derived(); +#ifndef MYSQL_CLIENT bool write_post_header_for_derived(IO_CACHE* file); +#endif }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ba9f382fc33..64e7b2cdccf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -257,6 +257,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; /* Flag set if setup_tables already done */ #define OPTION_SETUP_TABLES_DONE (1L << 30) +/* + Maximum length of time zone name that we support + (Time zone name is char(64) in db). mysqlbinlog needs it. +*/ +#define MAX_TIME_ZONE_NAME_LENGTH 72 + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT diff --git a/sql/set_var.cc b/sql/set_var.cc index 23dbb22399b..9e74c9452da 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2095,27 +2095,6 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_character_set_server::check(THD *thd, set_var *var) -{ - /* - To be perfect we should fail even if we are a 5.0.3 slave, a 4.1 master, - and user wants to change our global character set variables. Because - replicating a 4.1 assumes those are not changed. But that's not easy to - do. - */ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_character_set::check(thd,var); -} -#endif - CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2208,20 +2187,6 @@ void sys_var_collation_database::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_collation_server::check(THD *thd, set_var *var) -{ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_collation::check(thd,var); -} -#endif bool sys_var_collation_server::update(THD *thd, set_var *var) { @@ -2560,16 +2525,6 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var) String str(buff, sizeof(buff), &my_charset_latin1); String *res= var->value->val_str(&str); -#if defined(HAVE_REPLICATION) - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), "time zone"); - return 1; - } -#endif - if (!(var->save_result.time_zone= my_tz_find(res, thd->lex->time_zone_tables_used))) { @@ -2605,7 +2560,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, if (type == OPT_GLOBAL) return (byte *)(global_system_variables.time_zone->get_name()->ptr()); else + { + /* + This is an ugly fix for replication: we don't replicate properly queries + invoking system variables' values to update tables; but + CONVERT_TZ(,,@@session.time_zone) is so popular that we make it + replicable (i.e. we tell the binlog code to store the session + timezone). If it's the global value which was used we can't replicate + (binlog code stores session value only). + */ + thd->time_zone_used= 1; return (byte *)(thd->variables.time_zone->get_name()->ptr()); + } } diff --git a/sql/set_var.h b/sql/set_var.h index d78c228c142..585f6df3547 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set public: sys_var_character_set_server(const char *name_arg) : sys_var_character_set(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; @@ -603,9 +600,6 @@ class sys_var_collation_server :public sys_var_collation { public: sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif 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); diff --git a/sql/slave.cc b/sql/slave.cc index 73dd0fd13c3..9e42206d4a3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it)."; We don't test equality of global collation_database either as it's is going to be deprecated (made read-only) in 4.1 very soon. The test is only relevant if master < 5.0.3 (we'll test only if it's older - than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores + than the 5 branch; < 5.0.4 were alpha...), as >= 5.0.4 master stores charset info in each binlog event. We don't do it for 3.23 because masters <3.23.50 hang on SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we @@ -1456,11 +1456,10 @@ be equal for replication to work"; such check will broke everything for them. (And now everything will work for them because by default both their master and slave will have 'SYSTEM' time zone). - - TODO: when the new replication of timezones is sorted out with Dmitri, - change >= '4' to == '4'. + This check is only necessary for 4.x masters (and < 5.0.4 masters but + those were alpha). */ - if ((*mysql->server_version >= '4') && + if ((*mysql->server_version == '4') && !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) && (master_res= mysql_store_result(mysql))) { @@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd) thd->variables.completion_type= 0; } +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) +{ + thd->variables.character_set_client= + global_system_variables.character_set_client; + thd->variables.collation_connection= + global_system_variables.collation_connection; + thd->variables.collation_server= + global_system_variables.collation_server; + thd->update_charset(); + rli->cached_charset_invalidate(); +} + /* init_slave_thread() */ diff --git a/sql/slave.h b/sql/slave.h index ee5541ffe08..bc41cd4deca 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -562,6 +562,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli); void rotate_relay_log(MASTER_INFO* mi); extern "C" pthread_handler_decl(handle_slave_io,arg); diff --git a/sql/tztime.cc b/sql/tztime.cc index bd9d49f0ab0..983c630071e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_PRINT("enter", ("time zone name='%s'", name ? ((String *)name)->c_ptr() : "NULL")); - DBUG_ASSERT(!time_zone_tables_exist || tz_tables); + DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread); if (!name) DBUG_RETURN(0); @@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) (const byte *)name->ptr(), name->length()))) result_tz= tmp_tzname->tz; - else if (time_zone_tables_exist) + else if (time_zone_tables_exist && tz_tables) result_tz= tz_load_from_open_tables(name, tz_tables); } @@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_RETURN(result_tz); } + +/* + A more standalone version of my_tz_find(): will open tz tables if needed. + This is so far only used by replication, where time zone setting does not + happen in the usual query context. + + SYNOPSIS + my_tz_find_with_opening_tz_tables() + thd - pointer to thread's THD structure + name - time zone specification + + DESCRIPTION + This function tries to find a time zone which matches the named passed in + argument. If it fails, it will open time zone tables and re-try the + search. + This function is needed for the slave SQL thread, which does not do the + addition of time zone tables which is usually done during query parsing + (as time zone setting by slave does not happen in mysql_parse() but + before). So it needs to open tz tables by itself if needed. + See notes of my_tz_find() as they also apply here. + + RETURN VALUE + Pointer to corresponding Time_zone object. 0 - in case of bad time zone + specification or other error. + +*/ +Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name) +{ + Time_zone *tz; + DBUG_ENTER("my_tz_find_with_opening_tables"); + DBUG_ASSERT(thd); + DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only + if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist) + { + /* + Probably we have not loaded this time zone yet so let us look it up in + our time zone tables. Note that if we don't have tz tables on this + slave, we don't even try. + */ + TABLE_LIST tables[4]; + TABLE_LIST *dummy; + TABLE_LIST **dummyp= &dummy; + tz_init_table_list(tables, &dummyp); + if (simple_open_n_lock_tables(thd, tables)) + DBUG_RETURN(0); + tz= my_tz_find(name, tables); + /* We need to close tables _now_ to not pollute coming query */ + close_thread_tables(thd); + } + DBUG_RETURN(tz); +} + #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ diff --git a/sql/tztime.h b/sql/tztime.h index caf663fc8cb..777e521d761 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC; extern Time_zone * my_tz_SYSTEM; extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr); extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables); +extern Time_zone * my_tz_find_with_opening_tz_tables(THD *thd, const String *name); extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap); extern void my_tz_free(); @@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table, return FALSE; } -/* - Maximum length of time zone name that we support - (Time zone name is char(64) in db) -*/ -#define MAX_TIME_ZONE_NAME_LENGTH 72 - #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ From 135979d9593f412e4b119a76830fe44adf8950c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 10:39:26 +0100 Subject: [PATCH 12/16] Revert the inclusion of 'signal.h' as the module contains 'kill()'. server-tools/instance-manager/instance.cc: Revert the inclusion of 'signal.h' as this module contains 'kill()'. --- server-tools/instance-manager/instance.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index f5effe68c64..00fcf6c3a98 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include From 0550fead3bb28b757998bafa57326197e6779fa0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 11:38:51 +0100 Subject: [PATCH 13/16] disabling rpl_timezone.test if --ps-protocol, as binlogging of CONVERT_TZ(,,@@time_zone) fails there; until we find reason (me and possibly Konstantin). mysql-test/t/rpl_timezone.test: disabling test if --ps-protocol, until we find reason sql/slave.cc: fixing comment --- mysql-test/t/rpl_timezone.test | 11 +++++++++++ sql/slave.cc | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test index a49cdd0acd2..cc8dcb6ce26 100644 --- a/mysql-test/t/rpl_timezone.test +++ b/mysql-test/t/rpl_timezone.test @@ -1,4 +1,15 @@ # Test of replication of time zones. + +# There is currently some bug possibly in prepared statements (this +# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr() +# is called only at prepare time, not at execution time. So, +# thd->time_zone_used is not equal to 1 (it is back to 0, because of +# reset_thd_for_next_command called at execution time), so the +# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem +# and possibly Konstantin). + +--disable_ps_protocol + source include/master-slave.inc; # Some preparations diff --git a/sql/slave.cc b/sql/slave.cc index 9e42206d4a3..c92350f4a2f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it)."; We don't test equality of global collation_database either as it's is going to be deprecated (made read-only) in 4.1 very soon. The test is only relevant if master < 5.0.3 (we'll test only if it's older - than the 5 branch; < 5.0.4 were alpha...), as >= 5.0.4 master stores + than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores charset info in each binlog event. We don't do it for 3.23 because masters <3.23.50 hang on SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we From a99cb51c9d93d34eedbc08a9fca793855e3b9e05 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 15:48:06 +0200 Subject: [PATCH 14/16] Hack to ensure that CHAR's created in 5.0 are not converted to VARCHAR even if the row type is dynamic (For 4.1 tables old 'VARCHAR' fields are converted to true VARCHAR in the next ALTER TABLE) This ensures that one can use MySQL 5.0 privilege tables with MySQL 4.1 mysql-test/r/information_schema.result: Update results (for .frm version number change) mysql-test/r/ndb_autodiscover.result: Update results (for .frm version number change) mysql-test/r/ps_1general.result: Update results (for .frm version number change) mysql-test/r/show_check.result: Update results (for .frm version number change) mysql-test/r/view.result: Update results (for .frm version number change) scripts/fill_func_tables.sh: Ensure that no privilege tables that is used in 4.1 uses VARCHAR scripts/mysql_create_system_tables.sh: Ensure that no privilege tables that is used in 4.1 uses VARCHAR scripts/mysql_fix_privilege_tables.sh: Fixed bug that made it impossible to run the script from the mysql source dist scripts/mysql_fix_privilege_tables.sql: Ensure that no privilege tables that is used in 4.1 uses VARCHAR sql/sql_table.cc: Only set create_info->varchar if we are using the new VARCHAR field sql/table.cc: Hack to ensure that CHAR's created in 5.0 are not converted to VARCHAR even if the row type is dynamic (For 4.1 tables old 'VARCHAR' fields are converted to true VARCHAR in the next ALTER TABLE) --- mysql-test/r/information_schema.result | 5 ++- mysql-test/r/ndb_autodiscover.result | 4 +-- mysql-test/r/ps_1general.result | 2 +- mysql-test/r/show_check.result | 42 +++++++++++++------------- mysql-test/r/view.result | 4 +-- scripts/fill_func_tables.sh | 8 ++--- scripts/mysql_create_system_tables.sh | 10 +++--- scripts/mysql_fix_privilege_tables.sh | 2 +- scripts/mysql_fix_privilege_tables.sql | 42 +++++++++++++++++++++++--- sql/sql_table.cc | 9 ++---- sql/table.cc | 10 ++++++ 11 files changed, 87 insertions(+), 51 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index dc456e80e63..1c3525c1508 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -118,8 +118,8 @@ t2 t3 show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL -t3 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t3 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view show full columns from t3 like "a%"; Field Type Collation Null Key Default Extra Privileges Comment @@ -432,7 +432,6 @@ information_schema.tables) union select version from information_schema.tables; s1 0 -9 10 drop table t1; SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 38b34579f03..27ebda36669 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -144,8 +144,8 @@ Handler_discover 1 flush tables; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t6 MyISAM 9 Fixed 1 260 # # # 0 NULL # # NULL # NULL # -t7 ndbcluster 9 Fixed 1 276 # # # 0 NULL # # NULL # NULL # +t6 MyISAM 10 Fixed 1 260 # # # 0 NULL # # NULL # NULL # +t7 ndbcluster 10 Fixed 1 276 # # # 0 NULL # # NULL # NULL # show status like 'handler_discover%'; Variable_name Value Handler_discover 2 diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index cd3c8e162f7..342b3e3ef06 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -290,7 +290,7 @@ t2 1 t2_idx 1 b A NULL NULL NULL YES BTREE prepare stmt4 from ' show table status from test like ''t2%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show table status from test like ''t9%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 15cae7646f9..7c34481b519 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -315,57 +315,57 @@ insert into t2 values (1),(2); insert into t3 values (1,1),(2,2); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (3),(4); insert into t2 values (3),(4); insert into t3 values (3,3),(4,4); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (5); insert into t2 values (5); insert into t3 values (5,5); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1 where a=3; delete from t2 where b=3; delete from t3 where a=3; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1; delete from t2; delete from t3; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (5); insert into t2 values (5); insert into t3 values (5,5); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1 where a=5; delete from t2 where b=5; delete from t3 where a=5; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL drop table t1, t2, t3; create database mysqltest; show create database mysqltest; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 75459bd960b..ae1bb42cc29 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -149,7 +149,7 @@ v5 VIEW v6 VIEW show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view @@ -1115,7 +1115,7 @@ select * from v1; ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s) drop view v1; drop table t1; diff --git a/scripts/fill_func_tables.sh b/scripts/fill_func_tables.sh index 459afee2fe1..203c730dd9a 100644 --- a/scripts/fill_func_tables.sh +++ b/scripts/fill_func_tables.sh @@ -131,8 +131,8 @@ print "USE mysql_help;\n"; print "DROP TABLE IF EXISTS function;\n"; print "CREATE TABLE function ("; print " func_id int unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; +print " name char(64) not null,"; +print " url char(128) not null,"; print " description text not null,"; print " example text not null,"; print " min_args tinyint not null,"; @@ -145,8 +145,8 @@ print ") type=myisam;\n\n"; print "DROP TABLE IF EXISTS function_category_name;\n"; print "CREATE TABLE function_category_name ("; print " cat_id smallint unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; +print " name char(64) not null,"; +print " url char(128) not null,"; print " date_created datetime not null,"; print " last_modified timestamp not null,"; print " primary key (cat_id)"; diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index d87113d3656..0260bdea887 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -269,11 +269,11 @@ then c_ht="$c_ht CREATE TABLE help_topic (" c_ht="$c_ht help_topic_id int unsigned not null," - c_ht="$c_ht name varchar(64) not null," + c_ht="$c_ht name char(64) not null," c_ht="$c_ht help_category_id smallint unsigned not null," c_ht="$c_ht description text not null," c_ht="$c_ht example text not null," - c_ht="$c_ht url varchar(128) not null," + c_ht="$c_ht url char(128) not null," c_ht="$c_ht primary key (help_topic_id)," c_ht="$c_ht unique index (name)" c_ht="$c_ht ) engine=MyISAM" @@ -291,9 +291,9 @@ then c_hc="$c_hc CREATE TABLE help_category (" c_hc="$c_hc help_category_id smallint unsigned not null," - c_hc="$c_hc name varchar(64) not null," + c_hc="$c_hc name char(64) not null," c_hc="$c_hc parent_category_id smallint unsigned null," - c_hc="$c_hc url varchar(128) not null," + c_hc="$c_hc url char(128) not null," c_hc="$c_hc primary key (help_category_id)," c_hc="$c_hc unique index (name)" c_hc="$c_hc ) engine=MyISAM" @@ -309,7 +309,7 @@ then c_hk="$c_hk CREATE TABLE help_keyword (" c_hk="$c_hk help_keyword_id int unsigned not null," - c_hk="$c_hk name varchar(64) not null," + c_hk="$c_hk name char(64) not null," c_hk="$c_hk primary key (help_keyword_id)," c_hk="$c_hk unique index (name)" c_hk="$c_hk ) engine=MyISAM" diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index d5c96532782..d080b68b268 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -13,7 +13,7 @@ args="" port="" socket="" database="mysql" -bindir="." +bindir="" pkgdatadir="@pkgdatadir@" print_defaults_bindir="." diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 2310e8d0bef..344f8ca5bb3 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -307,19 +307,19 @@ KEY Grantor (Grantor) CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, -name varchar(64) not null, +name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, -url varchar(128) not null, +url char(128) not null, primary key (help_topic_id), unique index (name) ) CHARACTER SET utf8 comment='help topics'; CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, -name varchar(64) not null, +name char(64) not null, parent_category_id smallint unsigned null, -url varchar(128) not null, +url char(128) not null, primary key (help_category_id), unique index (name) ) CHARACTER SET utf8 comment='help categories'; @@ -332,7 +332,7 @@ primary key (help_keyword_id, help_topic_id) CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, -name varchar(64) not null, +name char(64) not null, primary key (help_keyword_id), unique index (name) ) CHARACTER SET utf8 comment='help keywords'; @@ -479,3 +479,35 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT 0 NOT NULL; + +# +# Change all varchar fields in privilege tables to CHAR, to ensure that +# we can use the privilege tables in MySQL 4.1 +# Note that for this hack to work, we must change all CHAR() columns at +# the same time +# + +ALTER TABLE mysql.user +modify Host char(60) binary DEFAULT '' NOT NULL, +modify User char(16) binary DEFAULT '' NOT NULL, +modify Password char(41) binary DEFAULT '' NOT NULL; + +ALTER TABLE mysql.db +modify Host char(60) binary DEFAULT '' NOT NULL, +modify Db char(64) binary DEFAULT '' NOT NULL, +modify User char(16) binary DEFAULT '' NOT NULL; + +ALTER TABLE mysql.host +modify Host char(60) binary DEFAULT '' NOT NULL, +modify Db char(64) binary DEFAULT '' NOT NULL; + +ALTER TABLE help_topic +modify name char(64) not null, +modify url char(128) not null; + +ALTER TABLE help_category +modify name char(64) not null, +modify url char(128) not null; + +ALTER TABLE help_keyword +modify name char(64) not null; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 82d887891cf..b125eeaf03a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -613,7 +613,7 @@ int prepare_create_field(create_field *sql_field, Prepares the table and key structures for table creation. NOTES - sets create_info->varchar if the table has a varchar or blob. + sets create_info->varchar if the table has a varchar RETURN VALUES 0 ok @@ -862,12 +862,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ×tamps, ×tamps_with_niladic, file->table_flags())) DBUG_RETURN(-1); - if (sql_field->sql_type == FIELD_TYPE_BLOB || - sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB || - sql_field->sql_type == FIELD_TYPE_TINY_BLOB || - sql_field->sql_type == FIELD_TYPE_LONG_BLOB || - sql_field->sql_type == FIELD_TYPE_GEOMETRY || - sql_field->sql_type == MYSQL_TYPE_VARCHAR) + if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) create_info->varchar= 1; sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) diff --git a/sql/table.cc b/sql/table.cc index 939690395d4..9238d8aa68e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -149,6 +149,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, *fn_ext(index_file)='\0'; // Remove .frm extension share->frm_version= head[2]; + /* + Check if .frm file created by MySQL 5.0. In this case we want to + display CHAR fields as CHAR and not as VARCHAR. + We do it this way as we want to keep the old frm version to enable + MySQL 4.1 to read these files. + */ + if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5) + share->frm_version= FRM_VER_TRUE_VARCHAR; + share->db_type= ha_checktype((enum db_type) (uint) *(head+3)); share->db_create_options= db_create_options=uint2korr(head+30); share->db_options_in_use= share->db_create_options; @@ -1317,6 +1326,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers int2store(fileinfo+30,create_info->table_options); fileinfo[32]=0; // No filename anymore + fileinfo[33]=5; // Mark for 5.0 frm file int4store(fileinfo+34,create_info->avg_row_length); fileinfo[38]= (create_info->default_table_charset ? create_info->default_table_charset->number : 0); From 06abeb4f639d8f06901588c4a958cba3eaee3a74 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 15:57:24 +0200 Subject: [PATCH 15/16] - Added new error message. - Changed error message in sql_acl.cc - Added some more tests for GRANT. Docs/mysqld_error.txt: Added new error message. mysql-test/r/grant2.result: Error message changed. mysql-test/r/grant3.result: Clean up. mysql-test/t/grant2.test: Error message changed. sql/share/errmsg.txt: Added new error message. sql/sql_acl.cc: Changed error message. mysql-test/t/grant3.test: Error message changed. --- Docs/mysqld_error.txt | 2 ++ mysql-test/r/grant2.result | 2 +- mysql-test/r/grant3.result | 17 +++++++++++++++++ mysql-test/t/grant2.test | 2 +- mysql-test/t/grant3-master.opt | 1 + mysql-test/t/grant3.test | 32 ++++++++++++++++++++++++++++++++ sql/share/errmsg.txt | 2 ++ sql/sql_acl.cc | 2 +- 8 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/grant3.result create mode 100644 mysql-test/t/grant3-master.opt create mode 100644 mysql-test/t/grant3.test diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt index 6370d8aac46..7f5560a5914 100644 --- a/Docs/mysqld_error.txt +++ b/Docs/mysqld_error.txt @@ -595,3 +595,5 @@ character-set=latin1 "Invalid ON UPDATE clause for '%-.64s' field", #define ER_UNSUPPORTED_PS 1295 "This command is not supported in the prepared statement protocol yet", +#define ER_CANT_CREATE_USER_WITH_GRANT 1296 +"You are not allowed to create a user with GRANT" diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index e6db7bd682f..ecd43cc2860 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -165,7 +165,7 @@ GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%' GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%' drop user 'mysqltest_1', 'mysqltest_3'; grant all on test.t1 to 'mysqltest_1'; -ERROR 42000: 'root'@'localhost' is not allowed to create new users +ERROR HY000: You are not allowed to create a user with GRANT drop user 'mysqltest_1'; ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%' drop table t1, t2; diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result new file mode 100644 index 00000000000..ae37db3af42 --- /dev/null +++ b/mysql-test/r/grant3.result @@ -0,0 +1,17 @@ +SET NAMES binary; +drop table if exists t1; +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; +create user mysqltest_1@localhost; +grant grant option on mysql.* to mysqltest_1@localhost; +grant select on `my\_1`.* to mysqltest_1@localhost with grant option; +grant select on `my\_1`.* to mysqltest_2@localhost; +ERROR HY000: You are not allowed to create a user with GRANT +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index f86cf2a1db7..7aefbb5d9ff 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -179,7 +179,7 @@ show grants for 'mysqltest_1'; drop user 'mysqltest_1', 'mysqltest_3'; # # Grant must not create user ---error 1211 +--error 1410 grant all on test.t1 to 'mysqltest_1'; --error 1396 drop user 'mysqltest_1'; diff --git a/mysql-test/t/grant3-master.opt b/mysql-test/t/grant3-master.opt new file mode 100644 index 00000000000..4b11f5902c1 --- /dev/null +++ b/mysql-test/t/grant3-master.opt @@ -0,0 +1 @@ +--safe-user-create diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test new file mode 100644 index 00000000000..dca4ff9496e --- /dev/null +++ b/mysql-test/t/grant3.test @@ -0,0 +1,32 @@ +# Test of GRANT commands + +SET NAMES binary; +connect (master,localhost,root,,); +connection master; + +# Cleanup +--disable_warnings +drop table if exists t1; +--enable_warnings + +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; + +create user mysqltest_1@localhost; +grant grant option on mysql.* to mysqltest_1@localhost; +grant select on `my\_1`.* to mysqltest_1@localhost with grant option; +connect (user_a,localhost,mysqltest_1,,); +connection user_a; +--error 1410 +grant select on `my\_1`.* to mysqltest_2@localhost; +disconnect user_a; +connection default; + +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d4caeebb70c..886c37b7061 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5332,3 +5332,5 @@ ER_STARTUP eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR eng "Can't load value from file with fixed size rows to variable" +ER_CANT_CREATE_USER_WITH_GRANT + eng "You are not allowed to create a user with GRANT" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c51e5e00aa1..de5df4559db 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1627,7 +1627,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, else if (((thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER) && !password_len) || !create_user) { - my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0), + my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0), thd->user, thd->host_or_ip); goto end; } From 27a711b4cb0f58b08794d8d85284c8220404e6c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 15:12:05 +0100 Subject: [PATCH 16/16] mysql-test-run.sh, mysql-test-run.pl: InnoDB needs longer start time for second slave on slow hosts mysql-test/mysql-test-run.pl: InnoDB needs longer start time for second slave on slow hosts mysql-test/mysql-test-run.sh: InnoDB needs longer start time for second slave on slow hosts --- mysql-test/mysql-test-run.pl | 6 +++--- mysql-test/mysql-test-run.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 80ba98e4e97..73ca47ac809 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -578,7 +578,7 @@ sub command_line_setup () { $slave->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave.pid"; $slave->[0]->{'path_mysock'}= "$opt_tmpdir/slave.sock"; $slave->[0]->{'path_myport'}= $opt_slave_myport; - $slave->[0]->{'start_timeout'}= 400; + $slave->[0]->{'start_timeout'}= 400; $slave->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave1-data"; $slave->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave1.err"; @@ -586,7 +586,7 @@ sub command_line_setup () { $slave->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave1.pid"; $slave->[1]->{'path_mysock'}= "$opt_tmpdir/slave1.sock"; $slave->[1]->{'path_myport'}= $opt_slave_myport + 1; - $slave->[1]->{'start_timeout'}= 30; + $slave->[1]->{'start_timeout'}= 300; $slave->[2]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave2-data"; $slave->[2]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave2.err"; @@ -594,7 +594,7 @@ sub command_line_setup () { $slave->[2]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave2.pid"; $slave->[2]->{'path_mysock'}= "$opt_tmpdir/slave2.sock"; $slave->[2]->{'path_myport'}= $opt_slave_myport + 2; - $slave->[2]->{'start_timeout'}= 30; + $slave->[2]->{'start_timeout'}= 300; # Do sanity checks of command line arguments diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 90846a2711a..c2cff2ed424 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -232,7 +232,7 @@ SLEEP_TIME_FOR_DELETE=10 SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables SLEEP_TIME_FOR_SECOND_MASTER=400 SLEEP_TIME_FOR_FIRST_SLAVE=400 -SLEEP_TIME_FOR_SECOND_SLAVE=30 +SLEEP_TIME_FOR_SECOND_SLAVE=300 CHARACTER_SET=latin1 DBUSER="" START_WAIT_TIMEOUT=10