From 13fea36d03529eefceadaa16b8a9d1faf3802eed Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Aug 2007 15:24:43 -0400 Subject: Bug#15776: 32-bit signed int used for length of blob Based on contributed patch from Martin Friebe, CLA from 2007-02-24. The parser lacked support for field sizes after signed long, when it should extend to 2**32-1. Now, we correct that limitation, and also make the error handling consistent for casts. mysql-test/r/type_blob.result: Verify that blobs may be created with the size that is already documented. Additionally, test the limits of several other types. mysql-test/t/type_blob.test: Verify that blobs may be created with the size that is already documented. Additionally, test the limits of several other types. sql/field.cc: atoi() insufficient to gauge the length of some fields. Change it to strtoul(). sql/item_create.cc: atoi() insufficient to gauge the length of some fields. Change it to strtoul(). If a casted length is too long, raise an error. sql/share/errmsg.txt: Change ER_TOO_BIG_FIELDLENGTH so that it can accept sizes larger than 2**15 -- instead, 2**32. sql/sql_yacc.yy: Make lengths take, in addition to NUM, LONG_NUM, ULONGLONG_NUM, and DECIMAL_NUM. sql/unireg.h: Define new constant. --- sql/field.cc | 16 ++++++++++++-- sql/item_create.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++--- sql/share/errmsg.txt | 60 ++++++++++++++++++++++++++-------------------------- sql/sql_yacc.yy | 55 +++++++++++++++++++++++------------------------ sql/unireg.h | 1 + 5 files changed, 126 insertions(+), 63 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 3f74210807b..2950f349580 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8395,8 +8395,20 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, (fld_type_modifier & NOT_NULL_FLAG) && fld_type != FIELD_TYPE_TIMESTAMP) flags|= NO_DEFAULT_VALUE_FLAG; - if (fld_length && !(length= (uint) atoi(fld_length))) - fld_length= 0; /* purecov: inspected */ + if (fld_length != 0) + { + errno= 0; + length= strtoul(fld_length, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH); + DBUG_RETURN(TRUE); + } + + if (length == 0) + fld_length= 0; /* purecov: inspected */ + } + sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1; switch (fld_type) { diff --git a/sql/item_create.cc b/sql/item_create.cc index 561613032bc..b7a9a1d7feb 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -464,8 +464,42 @@ Item *create_func_cast(Item *a, Cast_target cast_type, case ITEM_CAST_TIME: res= new Item_time_typecast(a); break; case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break; case ITEM_CAST_DECIMAL: - len= c_len ? atoi(c_len) : 0; - dec= c_dec ? atoi(c_dec) : 0; + if (c_len == NULL) + { + len= 0; + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_len, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name, + DECIMAL_MAX_PRECISION); + return NULL; + } + len= decoded_size; + } + + if (c_dec == NULL) + { + dec= 0; + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_dec, NULL, 10); + if ((errno != 0) || (decoded_size > UINT_MAX)) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name, + DECIMAL_MAX_SCALE); + return NULL; + } + dec= decoded_size; + } + my_decimal_trim(&len, &dec); if (len < dec) { @@ -486,8 +520,25 @@ Item *create_func_cast(Item *a, Cast_target cast_type, } res= new Item_decimal_typecast(a, len, dec); break; + case ITEM_CAST_CHAR: - len= c_len ? atoi(c_len) : -1; + if (c_len == NULL) + { + len= LL(-1); + } + else + { + ulong decoded_size; + errno= 0; + decoded_size= strtoul(c_len, NULL, 10); + if (errno != 0) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH); + return NULL; + } + len= decoded_size; + } + res= new Item_char_typecast(a, len, cs ? cs : current_thd->variables.collation_connection); break; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index a52ffa8216c..80ed9c788cc 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -1771,30 +1771,30 @@ ER_BLOB_USED_AS_KEY 42000 S1009 swe "En BLOB '%-.64s' kan inte vara nyckel med den anvnda tabelltypen" ukr "BLOB '%-.64s' Φ Ц æ" ER_TOO_BIG_FIELDLENGTH 42000 S1009 - cze "P-Bli velk dlka sloupce '%-.64s' (nejvce %d). Pouijte BLOB" - dan "For stor feltlngde for kolonne '%-.64s' (maks = %d). Brug BLOB i stedet" - nla "Te grote kolomlengte voor '%-.64s' (max = %d). Maak hiervoor gebruik van het type BLOB" - eng "Column length too big for column '%-.64s' (max = %d); use BLOB or TEXT instead" - jps "column '%-.64s' ,mۂ column ̑傫܂. (ő %d ܂). BLOB ɎgpĂ.", - est "Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB vljatpi" - fre "Champ '%-.64s' trop long (max = %d). Utilisez un BLOB" - ger "Feldlnge fr Feld '%-.64s' zu gro (maximal %d). BLOB- oder TEXT-Spaltentyp verwenden!" - greek " '%-.64s' (max = %d). BLOB" - hun "A(z) '%-.64s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb." - ita "La colonna '%-.64s' e` troppo grande (max=%d). Utilizza un BLOB." - jpn "column '%-.64s' ,ݤ column 礭¿ޤ. ( %d ޤ). BLOB 򤫤˻ѤƤ." - kor "Į '%-.64s' Į ̰ ʹ ϴ (ִ = %d). ſ BLOB ϼ." - nor "For stor nkkellengde for kolonne '%-.64s' (maks = %d). Bruk BLOB istedenfor" - norwegian-ny "For stor nykkellengde for felt '%-.64s' (maks = %d). Bruk BLOB istadenfor" - pol "Zbyt dua dugo? kolumny '%-.64s' (maks. = %d). W zamian uyj typu BLOB" - por "Comprimento da coluna '%-.64s' grande demais (max = %d); use BLOB em seu lugar" - rum "Lungimea coloanei '%-.64s' este prea lunga (maximum = %d). Foloseste BLOB mai bine" - rus " '%-.64s' ( = %d). BLOB TEXT " - serbian "Previe podataka za kolonu '%-.64s' (maksimum je %d). Upotrebite BLOB polje" - slo "Prli vek dka pre pole '%-.64s' (maximum = %d). Pouite BLOB" - spa "Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %d).Usar BLOB en su lugar" - swe "Fr stor kolumnlngd angiven fr '%-.64s' (max= %d). Anvnd en BLOB instllet" - ukr " '%-.64s' (max = %d). BLOB" + cze "P-Bli velk dlka sloupce '%-.64s' (nejvce %lu). Pouijte BLOB" + dan "For stor feltlngde for kolonne '%-.64s' (maks = %lu). Brug BLOB i stedet" + nla "Te grote kolomlengte voor '%-.64s' (max = %lu). Maak hiervoor gebruik van het type BLOB" + eng "Column length too big for column '%-.64s' (max = %lu); use BLOB or TEXT instead" + jps "column '%-.64s' ,mۂ column ̑傫܂. (ő %lu ܂). BLOB ɎgpĂ.", + est "Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %lu). Kasuta BLOB vljatpi" + fre "Champ '%-.64s' trop long (max = %lu). Utilisez un BLOB" + ger "Feldlnge fr Feld '%-.64s' zu gro (maximal %lu). BLOB- oder TEXT-Spaltentyp verwenden!" + greek " '%-.64s' (max = %lu). BLOB" + hun "A(z) '%-.64s' oszlop tul hosszu. (maximum = %lu). Hasznaljon BLOB tipust inkabb." + ita "La colonna '%-.64s' e` troppo grande (max=%lu). Utilizza un BLOB." + jpn "column '%-.64s' ,ݤ column 礭¿ޤ. ( %lu ޤ). BLOB 򤫤˻ѤƤ." + kor "Į '%-.64s' Į ̰ ʹ ϴ (ִ = %lu). ſ BLOB ϼ." + nor "For stor nkkellengde for kolonne '%-.64s' (maks = %lu). Bruk BLOB istedenfor" + norwegian-ny "For stor nykkellengde for felt '%-.64s' (maks = %lu). Bruk BLOB istadenfor" + pol "Zbyt dua dugo? kolumny '%-.64s' (maks. = %lu). W zamian uyj typu BLOB" + por "Comprimento da coluna '%-.64s' grande demais (max = %lu); use BLOB em seu lugar" + rum "Lungimea coloanei '%-.64s' este prea lunga (maximum = %lu). Foloseste BLOB mai bine" + rus " '%-.64s' ( = %lu). BLOB TEXT " + serbian "Previe podataka za kolonu '%-.64s' (maksimum je %lu). Upotrebite BLOB polje" + slo "Prli vek dka pre pole '%-.64s' (maximum = %lu). Pouite BLOB" + spa "Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %lu).Usar BLOB en su lugar" + swe "Fr stor kolumnlngd angiven fr '%-.64s' (max= %lu). Anvnd en BLOB instllet" + ukr " '%-.64s' (max = %lu). BLOB" ER_WRONG_AUTO_KEY 42000 S1009 cze "M-Bete mt pouze jedno AUTO pole a to mus bt definovno jako kl" dan "Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal vre indekseret" @@ -5508,11 +5508,11 @@ ER_SP_NO_RECURSION eng "Recursive stored functions and triggers are not allowed." ger "Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt" ER_TOO_BIG_SCALE 42000 S1009 - eng "Too big scale %d specified for column '%-.64s'. Maximum is %d." - ger "Zu groer Skalierungsfaktor %d fr Feld '%-.64s' angegeben. Maximum ist %d" + eng "Too big scale %lu specified for column '%-.64s'. Maximum is %d." + ger "Zu groer Skalierungsfaktor %lu fr Feld '%-.64s' angegeben. Maximum ist %d" ER_TOO_BIG_PRECISION 42000 S1009 - eng "Too big precision %d specified for column '%-.64s'. Maximum is %d." - ger "Zu groe Genauigkeit %d fr Feld '%-.64s' angegeben. Maximum ist %d" + eng "Too big precision %lu specified for column '%-.64s'. Maximum is %lu." + ger "Zu groe Genauigkeit %lu fr Feld '%-.64s' angegeben. Maximum ist %lu" ER_M_BIGGER_THAN_D 42000 S1009 eng "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.64s')." ger "Fr FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%-.64s')" @@ -5550,8 +5550,8 @@ ER_WARN_CANT_DROP_DEFAULT_KEYCACHE eng "Cannot drop default keycache" ger "Der vorgabemige Schlssel-Cache kann nicht gelscht werden" ER_TOO_BIG_DISPLAYWIDTH 42000 S1009 - eng "Display width out of range for column '%-.64s' (max = %d)" - ger "Anzeigebreite auerhalb des zulssigen Bereichs fr Spalte '%-.64s' (Maximum: %d)" + eng "Display width out of range for column '%-.64s' (max = %lu)" + ger "Anzeigebreite auerhalb des zulssigen Bereichs fr Spalte '%-.64s' (Maximum: %lu)" ER_XAER_DUPID XAE08 eng "XAER_DUPID: The XID already exists" ger "XAER_DUPID: Die XID existiert bereits" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 638da3b1bb0..c270e005454 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1171,7 +1171,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); single_multi table_wild_list table_wild_one opt_wild union_clause union_list precision subselect_start opt_and charset - subselect_end select_var_list select_var_list_init help opt_len + subselect_end select_var_list select_var_list_init help opt_field_length field_length opt_extended_describe prepare prepare_src execute deallocate statement sp_suid @@ -3010,7 +3010,7 @@ udf_type: field_list: field_list_item - | field_list ',' field_list_item; + | field_list ',' field_list_item; /* FIXME: Should this be backward? */ field_list_item: @@ -3111,45 +3111,38 @@ field_spec: }; type: - int_type opt_len field_options { $$=$1; } + int_type opt_field_length field_options { $$=$1; } | real_type opt_precision field_options { $$=$1; } | FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; } | BIT_SYM { Lex->length= (char*) "1"; $$=FIELD_TYPE_BIT; } - | BIT_SYM '(' NUM ')' { Lex->length= $3.str; - $$=FIELD_TYPE_BIT; } + | BIT_SYM field_length { $$=FIELD_TYPE_BIT; } | BOOL_SYM { Lex->length=(char*) "1"; $$=FIELD_TYPE_TINY; } | BOOLEAN_SYM { Lex->length=(char*) "1"; $$=FIELD_TYPE_TINY; } - | char '(' NUM ')' opt_binary { Lex->length=$3.str; - $$=FIELD_TYPE_STRING; } + | char field_length opt_binary { $$=FIELD_TYPE_STRING; } | char opt_binary { Lex->length=(char*) "1"; $$=FIELD_TYPE_STRING; } - | nchar '(' NUM ')' opt_bin_mod { Lex->length=$3.str; - $$=FIELD_TYPE_STRING; + | nchar field_length opt_bin_mod { $$=FIELD_TYPE_STRING; Lex->charset=national_charset_info; } | nchar opt_bin_mod { Lex->length=(char*) "1"; $$=FIELD_TYPE_STRING; Lex->charset=national_charset_info; } - | BINARY '(' NUM ')' { Lex->length=$3.str; - Lex->charset=&my_charset_bin; + | BINARY field_length { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_STRING; } | BINARY { Lex->length= (char*) "1"; Lex->charset=&my_charset_bin; $$=FIELD_TYPE_STRING; } - | varchar '(' NUM ')' opt_binary { Lex->length=$3.str; - $$= MYSQL_TYPE_VARCHAR; } - | nvarchar '(' NUM ')' opt_bin_mod { Lex->length=$3.str; - $$= MYSQL_TYPE_VARCHAR; + | varchar field_length opt_binary { $$= MYSQL_TYPE_VARCHAR; } + | nvarchar field_length opt_bin_mod { $$= MYSQL_TYPE_VARCHAR; Lex->charset=national_charset_info; } - | VARBINARY '(' NUM ')' { Lex->length=$3.str; - Lex->charset=&my_charset_bin; + | VARBINARY field_length { Lex->charset=&my_charset_bin; $$= MYSQL_TYPE_VARCHAR; } - | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; } + | YEAR_SYM opt_field_length field_options { $$=FIELD_TYPE_YEAR; } | DATE_SYM { $$=FIELD_TYPE_DATE; } | TIME_SYM { $$=FIELD_TYPE_TIME; } - | TIMESTAMP opt_len + | TIMESTAMP opt_field_length { if (YYTHD->variables.sql_mode & MODE_MAXDB) $$=FIELD_TYPE_DATETIME; @@ -3165,7 +3158,7 @@ type: | DATETIME { $$=FIELD_TYPE_DATETIME; } | TINYBLOB { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_TINY_BLOB; } - | BLOB_SYM opt_len { Lex->charset=&my_charset_bin; + | BLOB_SYM opt_field_length { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_BLOB; } | spatial_type { @@ -3187,7 +3180,7 @@ type: $$=FIELD_TYPE_MEDIUM_BLOB; } | LONG_SYM varchar opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } | TINYTEXT opt_binary { $$=FIELD_TYPE_TINY_BLOB; } - | TEXT_SYM opt_len opt_binary { $$=FIELD_TYPE_BLOB; } + | TEXT_SYM opt_field_length opt_binary { $$=FIELD_TYPE_BLOB; } | MEDIUMTEXT opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } | LONGTEXT opt_binary { $$=FIELD_TYPE_LONG_BLOB; } | DECIMAL_SYM float_options field_options @@ -3260,7 +3253,7 @@ real_type: float_options: /* empty */ { Lex->dec=Lex->length= (char*)0; } - | '(' NUM ')' { Lex->length=$2.str; Lex->dec= (char*)0; } + | field_length { Lex->dec= (char*)0; } | precision {}; precision: @@ -3283,9 +3276,15 @@ field_option: | UNSIGNED { Lex->type|= UNSIGNED_FLAG;} | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; }; -opt_len: - /* empty */ { Lex->length=(char*) 0; } /* use default length */ - | '(' NUM ')' { Lex->length= $2.str; }; +opt_field_length: + /* empty */ { Lex->length=(char*) NULL; } /* use default length */ + | field_length {}; + +field_length: + '(' LONG_NUM ')' { Lex->length= $2.str; } + | '(' ULONGLONG_NUM ')' { Lex->length= $2.str; } + | '(' DECIMAL_NUM ')' { Lex->length= $2.str; } + | '(' NUM ')' { Lex->length= $2.str; }; opt_precision: /* empty */ {} @@ -5466,9 +5465,9 @@ in_sum_expr: }; cast_type: - BINARY opt_len { $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; } - | CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; Lex->dec= 0; } - | NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; } + BINARY opt_field_length { $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; } + | CHAR_SYM opt_field_length opt_binary { $$=ITEM_CAST_CHAR; Lex->dec= 0; } + | NCHAR_SYM opt_field_length { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; } | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; } | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; } | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; } diff --git a/sql/unireg.h b/sql/unireg.h index 81ca18c1d32..0ab2a40048b 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -60,6 +60,7 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 #define MAX_FIELD_VARCHARLENGTH 65535 +#define MAX_FIELD_BLOBLENGTH UINT_MAX #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */ /* Max column width +1 */ -- cgit v1.2.1 From f7d8fb1cdde7a9655b984827547a7f4f85560834 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Feb 2008 14:10:46 +0100 Subject: Bug#33201 Crash occurs when granting update privilege on one column of a view When issuing a column level grant on a table which require pre-locking the server crashed. The reason behind the crash was that data structures used by the lock api wasn't properly reinitialized in the case of a column level grant. mysql-test/r/grant.result: * Added test case mysql-test/t/grant.test: * Added test case sql/sql_acl.cc: * The lock api is dending on the thd->lex object and this variable needs to be re-initialized when opened with a new set of tables than specified in the original statement. --- sql/sql_acl.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 134541368e9..703918329c2 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2878,6 +2878,12 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, } #endif + /* + The lock api is depending on the thd->lex variable which needs to be + re-initialized. + */ + Query_tables_list backup; + thd->lex->reset_n_backup_query_tables_list(&backup); if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ @@ -3016,6 +3022,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, send_ok(thd); /* Tables are automatically closed */ + thd->lex->restore_backup_query_tables_list(&backup); DBUG_RETURN(result); } -- cgit v1.2.1 From 8270d9875ff44900f3c57c15711c03d0b83cbe5d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Mar 2008 18:19:47 +0300 Subject: Fix for bug #34512: CAST( AVG( double ) AS DECIMAL ) returns wrong results Casting AVG() to DECIMAL led to incorrect results when the arguments had a non-DECIMAL type, because in this case Item_sum_avg::val_decimal() performed the division by the number of arguments twice. Fixed by changing Item_sum_avg::val_decimal() to not rely on Item_sum_sum::val_decimal(), i.e. calculate sum and divide using DECIMAL arithmetics for DECIMAL arguments, and utilize val_real() with subsequent conversion to DECIMAL otherwise. mysql-test/r/func_group.result: Added a test case for bug #34512. mysql-test/t/func_group.test: Added a test case for bug #34512. sql/item_sum.cc: Do not use Item_sum_sum::val_decimal() in Item_sum_avg::val_decimal() because the first one, depending on the arguments type, may return either the sum of the arguments, or the average calculated by the virtual val_real() method of Item_sum_avg. Instead, do our own calculation based on the arguments type. --- sql/item_sum.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 3d6d46ab3f4..f583fc7f988 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1206,7 +1206,15 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val) null_value=1; return NULL; } - sum_dec= Item_sum_sum::val_decimal(&sum_buff); + + /* + For non-DECIMAL hybrid_type the division will be done in + Item_sum_avg::val_real(). + */ + if (hybrid_type != DECIMAL_RESULT) + return val_decimal_from_real(val); + + sum_dec= dec_buffs + curr_dec_buff; int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt); my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment); return val; -- cgit v1.2.1 From ec62aba3f054b6fd3eabe774fac0da825a8baf33 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Mar 2008 11:12:12 +0100 Subject: Bug#34731: highest possible value for INT erroneously filtered by WHERE WHERE f1 < n ignored row if f1 was indexed integer column and f1 = TYPE_MAX ^ n = TYPE_MAX+1. The latter value when treated as TYPE overflowed (obviously). This was not handled, it is now. mysql-test/r/range.result: show that on an index int column, we no longer disregard a field val of TYPE_MAX in SELECT ... WHERE ... < TYPE_MAX+1 mysql-test/t/range.test: show that on an index int column, we no longer disregard a field val of TYPE_MAX in SELECT ... WHERE ... < TYPE_MAX+1 sql/opt_range.cc: Handle overflowing of int-types in range-optimizer. Unfortunately requires re-indentation of entire block. Overflow (err == 1) was handled, but only if field->cmp_type() != value->result_type(), which it just wasn't in our case. --- sql/opt_range.cc | 90 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 36 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a8cf0f67635..c3eddbd0abf 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4405,52 +4405,70 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, field->type() == FIELD_TYPE_DATETIME)) field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES; err= value->save_in_field_no_warnings(field, 1); - if (err > 0 && field->cmp_type() != value->result_type()) + if (err > 0) { - if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) && - value->result_type() == item_cmp_type(field->result_type(), - value->result_type())) - + if (field->cmp_type() != value->result_type()) { - tree= new (alloc) SEL_ARG(field, 0, 0); - tree->type= SEL_ARG::IMPOSSIBLE; - goto end; - } - else - { - /* - TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE - for the cases like int_field > 999999999999999999999999 as well. - */ - tree= 0; - if (err == 3 && field->type() == FIELD_TYPE_DATE && - (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC || - type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) ) + if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) && + value->result_type() == item_cmp_type(field->result_type(), + value->result_type())) + { + tree= new (alloc) SEL_ARG(field, 0, 0); + tree->type= SEL_ARG::IMPOSSIBLE; + goto end; + } + else { /* - We were saving DATETIME into a DATE column, the conversion went ok - but a non-zero time part was cut off. + TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE + for the cases like int_field > 999999999999999999999999 as well. + */ + tree= 0; + if (err == 3 && field->type() == FIELD_TYPE_DATE && + (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC || + type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) ) + { + /* + We were saving DATETIME into a DATE column, the conversion went ok + but a non-zero time part was cut off. - In MySQL's SQL dialect, DATE and DATETIME are compared as datetime - values. Index over a DATE column uses DATE comparison. Changing - from one comparison to the other is possible: + In MySQL's SQL dialect, DATE and DATETIME are compared as datetime + values. Index over a DATE column uses DATE comparison. Changing + from one comparison to the other is possible: - datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' - datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' + datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' + datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' - datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' - datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' + datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' + datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' - but we'll need to convert '>' to '>=' and '<' to '<='. This will - be done together with other types at the end of this function - (grep for field_is_equal_to_item) - */ + but we'll need to convert '>' to '>=' and '<' to '<='. This will + be done together with other types at the end of this function + (grep for field_is_equal_to_item) + */ + } + else + goto end; } - else - goto end; } - } - if (err < 0) + + /* + guaranteed at this point: err > 0; field and const of same type + If an integer got bounded (e.g. to within 0..255 / -128..127) + for < or >, set flags as for <= or >= (no NEAR_MAX / NEAR_MIN) + */ + else if (err == 1 && field->result_type() == INT_RESULT) + { + if (type == Item_func::LT_FUNC && (value->val_int() > 0)) + type = Item_func::LE_FUNC; + else if (type == Item_func::GT_FUNC && + !((Field_num*)field)->unsigned_flag && + !((Item_int*)value)->unsigned_flag && + (value->val_int() < 0)) + type = Item_func::GE_FUNC; + } + } + else if (err < 0) { field->table->in_use->variables.sql_mode= orig_sql_mode; /* This happens when we try to insert a NULL field in a not null column */ -- cgit v1.2.1 From d5f09a13def2462127a1b3c3f268866136f748d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2008 10:03:01 +0800 Subject: BUG#33029 5.0 to 5.1 replication fails on dup key when inserting using a trig in SP For all 5.0 and up to 5.1.12 exclusive, when a stored routine or trigger caused an INSERT into an AUTO_INCREMENT column, the generated AUTO_INCREMENT value should not be written into the binary log, which means if a statement does not generate AUTO_INCREMENT value itself, there will be no Intvar event (SET INSERT_ID) associated with it even if one of the stored routine or trigger caused generation of such a value. And meanwhile, when executing a stored routine or trigger, it would ignore the INSERT_ID value even if there is a INSERT_ID value available set by a SET INSERT_ID statement. Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is written into the binary log, and the value will be used if available when executing the stored routine or trigger. Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12 (referenced as the buggy versions in the text below), when a statement that generates AUTO_INCREMENT value by the top statement was executed in the body of a SP, all statements in the SP after this statement would be treated as if they had generated AUTO_INCREMENT by the top statement. When a statement that did not generate AUTO_INCREMENT value by the top statement but by a function/trigger called by it, an erroneous Intvar event would be associated with the statement, this erroneous INSERT_ID value wouldn't cause problem when replicating between masters and slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID value was not used when executing functions/triggers. But when replicating from buggy versions to 5.1.12 or newer, which will use the INSERT_ID value in functions/triggers, the erroneous value will be used, which would cause duplicate entry error and cause the slave to stop. The patch for 5.0 fixed it not to generate the erroneous Intvar event, another patch for 5.1 fixed it to ignore the SET INSERT_ID value when executing functions/triggers if it is replicating from a master of buggy versions. mysql-test/include/show_binlog_events.inc: add $binlog_start parameter to set the start position when show binlog events, if not set a default value will be used. mask out column 2(Pos), 4(Server_id), table_id, and file_id sql/sql_class.cc: Reset insert_id_used after each query in SP mysql-test/r/rpl_auto_increment_bug33029.result: Add test for bug33029, test if the master generate the erroneous event or not mysql-test/t/rpl_auto_increment_bug33029.test: Add test for bug33029, test if the master generate the erroneous event or not --- sql/sql_class.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e36ed0c425f..f541c8b3677 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -622,6 +622,13 @@ void THD::cleanup_after_query() { clear_next_insert_id= 0; next_insert_id= 0; + + /* + BUG#33029, if one statement in a SP set this member to 1, all + statment after this statement in the SP would be considered used + INSERT_ID value, reset this member after each query to fix this. + */ + insert_id_used= 0; } /* Reset rand_used so that detection of calls to rand() will save random -- cgit v1.2.1 From 9699767c952bf30ab4b18a15e131ba417745f855 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2008 23:11:59 +0400 Subject: Fixed bug #34763. Queries like: SELECT ROW(1, 2) IN (SELECT t1.a, 2) FROM t1 GROUP BY t1.a or SELECT ROW(1, 2) IN (SELECT t1.a, 2 FROM t2) FROM t1 GROUP BY t1.a lead to assertion failure in the Item_in_subselect::row_value_transformer method in debugging build, or to unexpected error message in release build: ERROR 1247 (42S22): Reference '' not supported (forward reference in item list) Unexpected error message and assertion failure have been eliminated. mysql-test/r/subselect3.result: Added test case for bug #34763. mysql-test/t/subselect3.test: Added test case for bug #34763. sql/item.cc: Fixed bug #34763. The Item_ref::fix_fields method has been modified to silently ignore not fixed outer references: by the definition, those references should be fixed later by the call to the fix_inner_refs function. sql/item_subselect.cc: Fixed bug #34763. The Item_in_subselect::row_value_transformer method has been modified to eliminate assertion failure on not fixed outer references: by the definition those references are allowed in this context and should be fixed later by the call to the fix_inner_refs function. --- sql/item.cc | 15 +++++++++------ sql/item_subselect.cc | 12 ++++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 53e7f124ccd..36612ddea44 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5451,13 +5451,16 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) DBUG_ASSERT(*ref); /* Check if this is an incorrect reference in a group function or forward - reference. Do not issue an error if this is an unnamed reference inside an - aggregate function. + reference. Do not issue an error if this is: + 1. outer reference (will be fixed later by the fix_inner_refs function); + 2. an unnamed reference inside an aggregate function. */ - if (((*ref)->with_sum_func && name && - !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && - current_sel->having_fix_field)) || - !(*ref)->fixed) + if (!((*ref)->type() == REF_ITEM && + ((Item_ref *)(*ref))->ref_type() == OUTER_REF) && + (((*ref)->with_sum_func && name && + !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && + current_sel->having_fix_field)) || + !(*ref)->fixed)) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, ((*ref)->with_sum_func? diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b3710841dfb..a03a7d739b2 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1232,7 +1232,11 @@ Item_in_subselect::row_value_transformer(JOIN *join) Item *item_having_part2= 0; for (uint i= 0; i < cols_num; i++) { - DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed); + DBUG_ASSERT(left_expr->fixed && + select_lex->ref_pointer_array[i]->fixed || + (select_lex->ref_pointer_array[i]->type() == REF_ITEM && + ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == + Item_ref::OUTER_REF)); if (select_lex->ref_pointer_array[i]-> check_cols(left_expr->element_index(i)->cols())) DBUG_RETURN(RES_ERROR); @@ -1306,7 +1310,11 @@ Item_in_subselect::row_value_transformer(JOIN *join) for (uint i= 0; i < cols_num; i++) { Item *item, *item_isnull; - DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed); + DBUG_ASSERT(left_expr->fixed && + select_lex->ref_pointer_array[i]->fixed || + (select_lex->ref_pointer_array[i]->type() == REF_ITEM && + ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == + Item_ref::OUTER_REF)); if (select_lex->ref_pointer_array[i]-> check_cols(left_expr->element_index(i)->cols())) DBUG_RETURN(RES_ERROR); -- cgit v1.2.1 From 6cf64b26d8eedae3e744335736aee44975899c19 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Mar 2008 20:19:04 +0200 Subject: Bug #18199 PURGE BINARY LOGS fails silently with missing logs; Bug #18453 Warning/error message if there is a mismatch between ... There were three problems: 1. the reported lack of warnings for the BEFORE syntax of PURGE; 2. the similar lack of warnings for the TO syntax; 3. incompatible behaviour between the two in that the latter blanked out regardlessly of presence or lack the actual file corresponding to an index record; the former version gave up at the first mismatch. fixed with deploying the warning's generation and synronizing logics of purge_logs() and purge_logs_before_date(). my_stat() is called in either of two branches of purge_logs() (responsible for the TO syntax of PURGE) similarly to how it has behaved in the BEFORE syntax. If there is no actual binlog file, my_stat returns NULL and my_delete is not invoked. A critical error is reported to the user if a file from the index could not be retrieved info about or deleted with a system error code different than ENOENT. sql/log.cc: generating warning in two functions. refining logics to call my_stat() by purge_logs() as it happens in purge_logs_before_date(). my_delete() is called only if my_stat() ensured existance of the file. A critical error is reported to the user if a file from the index could not be my_stat():ed or my_delete():d with an error different than ENOENT. sql/share/errmsg.txt: new error message mysql-test/include/show_binary_logs.inc: a new macro - shortcut of show binary logs mysql-test/r/binlog_index.result: new results mysql-test/t/binlog_index.test: a regression test for the bugs --- sql/log.cc | 153 ++++++++++++++++++++++++++++++++++++++++++--------- sql/share/errmsg.txt | 2 + 2 files changed, 129 insertions(+), 26 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index 0376facb473..1924821c91c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1180,6 +1180,8 @@ int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads) RETURN VALUES 0 ok LOG_INFO_EOF to_log not found + LOG_INFO_FATAL if any other than ENOENT error from + my_stat() or my_delete() */ int MYSQL_LOG::purge_logs(const char *to_log, @@ -1208,33 +1210,75 @@ int MYSQL_LOG::purge_logs(const char *to_log, while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && !log_in_use(log_info.log_file_name)) { - ulong file_size= 0; - if (decrease_log_space) //stat the file we want to delete + MY_STAT s; + if (!my_stat(log_info.log_file_name, &s, MYF(0))) { - MY_STAT s; - - /* - If we could not stat, we can't know the amount - of space that deletion will free. In most cases, - deletion won't work either, so it's not a problem. - */ - if (my_stat(log_info.log_file_name,&s,MYF(0))) - file_size= s.st_size; - else - sql_print_information("Failed to execute my_stat on file '%s'", + if (my_errno == ENOENT) + { + /* + It's not fatal if we can't stat a log file that does not exist; + If we could not stat, we won't delete. + */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + sql_print_information("Failed to execute my_stat on file '%s'", log_info.log_file_name); + my_errno= 0; + } + else + { + /* + Other than ENOENT are fatal + */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with getting info on being purged %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + error= LOG_INFO_FATAL; + goto err; + } + } + else + { + DBUG_PRINT("info",("purging %s",log_info.log_file_name)); + if (!my_delete(log_info.log_file_name, MYF(0))) + { + if (decrease_log_space) + *decrease_log_space-= s.st_size; + } + else + { + if (my_errno == ENOENT) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + sql_print_information("Failed to delete file '%s'", + log_info.log_file_name); + my_errno= 0; + } + else + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + error= LOG_INFO_FATAL; + goto err; + } + } } - /* - It's not fatal if we can't delete a log file ; - if we could delete it, take its size into account - */ - DBUG_PRINT("info",("purging %s",log_info.log_file_name)); - if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space) - *decrease_log_space-= file_size; if (find_next_log(&log_info, 0) || exit_loop) break; } - + /* If we get killed -9 here, the sysadmin would have to edit the log index file after restart - otherwise, this should be safe @@ -1263,6 +1307,8 @@ err: RETURN VALUES 0 ok LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated + LOG_INFO_FATAL if any other than ENOENT error from + my_stat() or my_delete() */ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) @@ -1286,11 +1332,66 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) while (strcmp(log_file_name, log_info.log_file_name) && !log_in_use(log_info.log_file_name)) { - /* It's not fatal even if we can't delete a log file */ - if (!my_stat(log_info.log_file_name, &stat_area, MYF(0)) || - stat_area.st_mtime >= purge_time) - break; - my_delete(log_info.log_file_name, MYF(0)); + if (!my_stat(log_info.log_file_name, &stat_area, MYF(0))) + { + if (my_errno == ENOENT) + { + /* + It's not fatal if we can't stat a log file that does not exist. + */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + sql_print_information("Failed to execute my_stat on file '%s'", + log_info.log_file_name); + my_errno= 0; + } + else + { + /* + Other than ENOENT are fatal + */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with getting info on being purged %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + error= LOG_INFO_FATAL; + goto err; + } + } + else + { + if (stat_area.st_mtime >= purge_time) + break; + if (my_delete(log_info.log_file_name, MYF(0))) + { + if (my_errno == ENOENT) + { + /* It's not fatal even if we can't delete a log file */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + sql_print_information("Failed to delete file '%s'", + log_info.log_file_name); + my_errno= 0; + } + else + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + error= LOG_INFO_FATAL; + goto err; + } + } + } if (find_next_log(&log_info, 0)) break; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 9e6cf462113..516dba1cd08 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5641,3 +5641,5 @@ ER_NAME_BECOMES_EMPTY eng "Name '%-.64s' has become ''" ER_AMBIGUOUS_FIELD_TERM eng "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY" +ER_LOG_PURGE_NO_FILE + eng "Being purged log %s was not found" -- cgit v1.2.1 From 3c5894baaa9dcc2d910d504ef073facfcd329f8e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Mar 2008 14:32:28 +0100 Subject: Bug#34529: Crash on complex Falcon I_S select after ALTER .. PARTITION BY When swapping out heap I_S tables to disk, this is done after plan refinement. Thus, READ_RECORD::file will still point to the (deleted) heap handler at start of execution. This causes segmentation fault if join buffering is used and the query is a star query where the result is found to be empty before accessing some table. In this case that table has not been initialized (i.e. had its READ_RECORD re-initialized) before the cleanup routine tries to close the handler. Fixed by updating READ_RECORD::file when changing handler. mysql-test/r/information_schema.result: Bug#34529: Test result. mysql-test/t/information_schema.test: Bug#34529: Test case. sql/sql_show.cc: Bug#34529: The fix. --- sql/sql_show.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 36d154181f8..a80319785bd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4073,9 +4073,11 @@ bool get_schema_tables_result(JOIN *join, { result= 1; join->error= 1; + tab->read_record.file= table_list->table->file; table_list->schema_table_state= executed_place; break; } + tab->read_record.file= table_list->table->file; table_list->schema_table_state= executed_place; } } -- cgit v1.2.1 From 5a6996dbcde4ca833f7936413cfa090cba060af5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Mar 2008 18:44:50 +0200 Subject: Bug #35178 INSERT_ID not written to binary log for inserts against BLACKHOLE backed tables binlogging of insert into a autoincrement blackhole table ignored an explicit set insert_id. Fixed with refining of the blackhole's insert method to call update_auto_increment() that prepares binlogging the insert query with the preceeding set insert_id. Note, as the engine does not store any actual data one has to explicitly provide to the server with the value of the autoincrement column via set insert_id. Otherwise binlogging will happend with the default set insert_id=1. mysql-test/r/blackhole.result: results changed mysql-test/t/blackhole.test: a regression test for the bug added sql/ha_blackhole.cc: blackhole's insert method is refined to call update_auto_increment() that prepares binlogging the insert query with the preceeding set insert_id. --- sql/ha_blackhole.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc index e477686d18e..01ede3d3bd2 100644 --- a/sql/ha_blackhole.cc +++ b/sql/ha_blackhole.cc @@ -115,7 +115,7 @@ const char *ha_blackhole::index_type(uint key_number) int ha_blackhole::write_row(byte * buf) { DBUG_ENTER("ha_blackhole::write_row"); - DBUG_RETURN(0); + DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0); } int ha_blackhole::rnd_init(bool scan) -- cgit v1.2.1 From cebb6727b3c8593283f81182d06c45ca69cc0304 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Mar 2008 17:23:17 +0200 Subject: Bug #26461: Intrinsic data type bool (1 byte) redefined to BOOL (4 bytes) The bool data type was redefined to BOOL (4 bytes on windows). Removed the #define and fixed some of the warnings that were uncovered by this. Note that the fix also disables 2 warnings : 4800 : 'type' : forcing value to bool 'true' or 'false' (performance warning) 4805: 'operation' : unsafe mix of type 'type' and type 'type' in operation These warnings will be handled in a separate bug, as they are performance related or bogus. Fixed to int the return type of functions that return more than 2 distinct values. CMakeLists.txt: Bug #26461: disable the C4800 and C4805 warnings temporarily include/config-win.h: Bug #26461: - no need for this define for Windows. - windows C++ compilers have a bool type include/my_global.h: Bug #26461: removed bool_defined (no longer needed) sql/handler.h: Bug #26461: bool functions must return boolean values sql/mysql_priv.h: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/procedure.h: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_acl.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_acl.h: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_analyse.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_analyse.h: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_base.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_db.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_delete.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_load.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_parse.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_prepare.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. sql/sql_update.cc: Bug #26461: fixed return type of functions that return more than 2 distinct values. --- sql/handler.h | 2 +- sql/mysql_priv.h | 14 +++++++------- sql/procedure.h | 2 +- sql/sql_acl.cc | 6 +++--- sql/sql_acl.h | 6 +++--- sql/sql_analyse.cc | 2 +- sql/sql_analyse.h | 2 +- sql/sql_base.cc | 2 +- sql/sql_db.cc | 2 +- sql/sql_delete.cc | 4 ++-- sql/sql_load.cc | 2 +- sql/sql_parse.cc | 4 ++-- sql/sql_prepare.cc | 6 +++--- sql/sql_update.cc | 2 +- 14 files changed, 28 insertions(+), 28 deletions(-) (limited to 'sql') diff --git a/sql/handler.h b/sql/handler.h index 74c09d2d9ee..aa3377c3868 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -815,7 +815,7 @@ public: { return HA_ADMIN_NOT_IMPLEMENTED; } /* end of the list of admin commands */ - virtual bool check_and_repair(THD *thd) { return HA_ERR_WRONG_COMMAND; } + virtual bool check_and_repair(THD *thd) { return TRUE; } virtual int dump(THD* thd, int fd = -1) { return HA_ERR_WRONG_COMMAND; } virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; } virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 59ec18e1a3d..0b488900ac5 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -597,8 +597,8 @@ bool check_merge_table_access(THD *thd, char *db, bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); -bool mysql_multi_update_prepare(THD *thd); -bool mysql_multi_delete_prepare(THD *thd); +int mysql_multi_update_prepare(THD *thd); +int mysql_multi_delete_prepare(THD *thd); bool mysql_insert_select_prepare(THD *thd); bool update_precheck(THD *thd, TABLE_LIST *tables); bool delete_precheck(THD *thd, TABLE_LIST *tables); @@ -691,7 +691,7 @@ struct Query_cache_query_flags uint build_table_path(char *buff, size_t bufflen, const char *db, const char *table, const char *ext); -bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); @@ -731,7 +731,7 @@ pthread_handler_t handle_one_connection(void *arg); pthread_handler_t handle_bootstrap(void *arg); void end_thread(THD *thd,bool put_in_cache); void flush_thread_cache(); -bool mysql_execute_command(THD *thd); +int mysql_execute_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); void log_slow_statement(THD *thd); @@ -862,7 +862,7 @@ void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table, enum_duplicates duplic); void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table, enum_duplicates duplic); -bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); +int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ha_rows rows, ulonglong options, bool reset_auto_increment); @@ -1106,7 +1106,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags); int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); -bool open_and_lock_tables(THD *thd,TABLE_LIST *tables); +int open_and_lock_tables(THD *thd,TABLE_LIST *tables); bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags); int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, @@ -1177,7 +1177,7 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table, bool eval_const_cond(COND *cond); /* sql_load.cc */ -bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list, +int mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list, List &fields_vars, List &set_fields, List &set_values_list, enum enum_duplicates handle_duplicates, bool ignore, diff --git a/sql/procedure.h b/sql/procedure.h index 850d5c74db4..f1fb433a6ee 100644 --- a/sql/procedure.h +++ b/sql/procedure.h @@ -144,7 +144,7 @@ public: virtual int send_row(List &fields)=0; virtual bool change_columns(List &fields)=0; virtual void update_refs(void) {} - virtual bool end_of_records() { return 0; } + virtual int end_of_records() { return 0; } }; Procedure *setup_procedure(THD *thd,ORDER *proc_param,select_result *result, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e9504f423ad..e773f754e18 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1382,7 +1382,7 @@ bool acl_check_host(const char *host, const char *ip) 1 ERROR ; In this case the error is sent to the client. */ -bool check_change_password(THD *thd, const char *host, const char *user, +int check_change_password(THD *thd, const char *host, const char *user, char *new_password, uint new_password_len) { if (!initialized) @@ -2763,7 +2763,7 @@ table_error: TRUE error */ -bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, +int mysql_table_grant(THD *thd, TABLE_LIST *table_list, List &user_list, List &columns, ulong rights, bool revoke_grant) @@ -5805,7 +5805,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, < 0 Error. Error message not yet sent. */ -bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, +int sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, bool is_proc) { Security_context *sctx= thd->security_ctx; diff --git a/sql/sql_acl.h b/sql/sql_acl.h index b2007ccdf47..1efcd2e3b6b 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -183,13 +183,13 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd, bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, char *ip, char *db); bool acl_check_host(const char *host, const char *ip); -bool check_change_password(THD *thd, const char *host, const char *user, +int check_change_password(THD *thd, const char *host, const char *user, char *password, uint password_len); bool change_password(THD *thd, const char *host, const char *user, char *password); bool mysql_grant(THD *thd, const char *db, List &user_list, ulong rights, bool revoke); -bool mysql_table_grant(THD *thd, TABLE_LIST *table, List &user_list, +int mysql_table_grant(THD *thd, TABLE_LIST *table, List &user_list, List &column_list, ulong rights, bool revoke); bool mysql_routine_grant(THD *thd, TABLE_LIST *table, bool is_proc, @@ -225,7 +225,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, bool is_proc); -bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, +int sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, bool is_proc); bool check_routine_level_acl(THD *thd, const char *db, const char *name, bool is_proc); diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 95a7fb3d34d..2e90d00f8aa 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -683,7 +683,7 @@ int analyse::send_row(List &field_list __attribute__((unused))) } // analyse::send_row -bool analyse::end_of_records() +int analyse::end_of_records() { field_info **f = f_info; char buff[MAX_FIELD_WIDTH]; diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h index 21a37209e89..2a4226b2d95 100644 --- a/sql/sql_analyse.h +++ b/sql/sql_analyse.h @@ -350,7 +350,7 @@ public: virtual bool change_columns(List &fields); virtual int send_row(List &fields); virtual void end_group(void) {} - virtual bool end_of_records(void); + virtual int end_of_records(void); friend Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result, List &field_list); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c9f20b3d71b..533b0070fee 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3046,7 +3046,7 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) The lock will automaticaly be freed by close_thread_tables() */ -bool open_and_lock_tables(THD *thd, TABLE_LIST *tables) +int open_and_lock_tables(THD *thd, TABLE_LIST *tables) { uint counter; bool need_reopen; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 91b0c02d23b..e25ede1be03 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -449,7 +449,7 @@ bool load_db_opt_by_name(THD *thd, const char *db_name, */ -bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) { char path[FN_REFLEN+16]; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a28a39a769d..af895c172ff 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -370,7 +370,7 @@ cleanup: FALSE OK TRUE error */ -bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) +int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; @@ -433,7 +433,7 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) TRUE Error */ -bool mysql_multi_delete_prepare(THD *thd) +int mysql_multi_delete_prepare(THD *thd) { LEX *lex= thd->lex; TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index d687ceff393..4da3c19bb3c 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -110,7 +110,7 @@ static bool write_execute_load_query_log_event(THD *thd, TRUE - error / FALSE - success */ -bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, +int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List &fields_vars, List &set_fields, List &set_values, enum enum_duplicates handle_duplicates, bool ignore, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8bdbd812529..98e04e45bdd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2500,10 +2500,10 @@ static void reset_one_shot_variables(THD *thd) TRUE Error */ -bool +int mysql_execute_command(THD *thd) { - bool res= FALSE; + int res= FALSE; bool need_start_waiting= FALSE; // have protection against global read lock int up_result= 0; LEX *lex= thd->lex; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18cfd8d7dfc..220b9a0bcd8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1403,7 +1403,7 @@ error: */ static bool select_like_stmt_test(Prepared_statement *stmt, - bool (*specific_prepare)(THD *thd), + int (*specific_prepare)(THD *thd), ulong setup_tables_done_option) { DBUG_ENTER("select_like_stmt_test"); @@ -1441,7 +1441,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt, static bool select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt, TABLE_LIST *tables, - bool (*specific_prepare)(THD *thd), + int (*specific_prepare)(THD *thd), ulong setup_tables_done_option) { DBUG_ENTER("select_like_stmt_test_with_open_n_lock"); @@ -1630,7 +1630,7 @@ error: because mysql_handle_derived uses local tables lists. */ -static bool mysql_insert_select_prepare_tester(THD *thd) +static int mysql_insert_select_prepare_tester(THD *thd) { SELECT_LEX *first_select= &thd->lex->select_lex; TABLE_LIST *second_table= ((TABLE_LIST*)first_select->table_list.first)-> diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 84349a40977..541704cfaf1 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -716,7 +716,7 @@ static table_map get_table_map(List *items) TRUE Error */ -bool mysql_multi_update_prepare(THD *thd) +int mysql_multi_update_prepare(THD *thd) { LEX *lex= thd->lex; TABLE_LIST *table_list= lex->query_tables; -- cgit v1.2.1 From 0b8342ba4e3c0426569f3256a8d951e168a7d52d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Mar 2008 22:43:12 +0400 Subject: Fixed bug #35193. View definition as SELECT ... FROM DUAL WHERE ... has valid syntax, but use of such view in SELECT or SHOW CREATE VIEW syntax causes unexpected syntax error. Server omits FROM DUAL clause when storing view body string in a .frm file for further evaluation. However, syntax of SELECT-witout-FROM query is more restrictive than SELECT FROM DUAL syntax, and doesn't allow the WHERE clause. NOTE: this syntax difference is not documented. View registration procedure has been modified to preserve original structure of view's body. mysql-test/r/view.result: Added test case for bug #35193. mysql-test/t/view.test: Added test case for bug #35193. sql/sql_select.cc: Fixed bug #35193. The st_select_lex::print function always omits FROM DUAL clause, even if original SELECT query has the WHERE clause. The mysql_register_view function uses this function to reconstruct a body of view's AS clause for further evaluation and stores that reconstructed clause in a .frm file. SELECT without FROM syntax is more restrictive than SELECT FROM DUAL syntax: second one allows the WHERE clause, but first one is not. Use of this view in SELECT or SHOW CREATE VIEW queries causes unexpected syntax errors. The st_select_lex::print function has been modified to reconstruct FROM DUAL clause in queries when needed. TODO: Syntax difference is not documented and should be eliminated, however improvement of the SELECT-without-FROM syntax is not trivial and leads to significant modification of grammar file because of additional shift/reduce conflicts. --- sql/sql_select.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6392f7c4299..bb3030a721c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15806,6 +15806,14 @@ void st_select_lex::print(THD *thd, String *str) /* go through join tree */ print_join(thd, str, &top_join_list); } + else if (where) + { + /* + "SELECT 1 FROM DUAL WHERE 2" should not be printed as + "SELECT 1 WHERE 2": the 1st syntax is valid, but the 2nd is not. + */ + str->append(STRING_WITH_LEN(" from DUAL ")); + } // Where Item *cur_where= where; -- cgit v1.2.1 From 73e1c5ae10994373df5d929974be02edffae70e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Mar 2008 14:52:10 -0400 Subject: Fix minor complaints of Marc Alff, for patch against B-g#15776. mysql-test/t/type_blob.test: Drop table in case we start from a bad state. sql/sql_yacc.yy: yacc/bison is left-recursive, so FIXME statement is wrong. --- sql/sql_yacc.yy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c270e005454..d47e6679269 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3010,7 +3010,7 @@ udf_type: field_list: field_list_item - | field_list ',' field_list_item; /* FIXME: Should this be backward? */ + | field_list ',' field_list_item; field_list_item: -- cgit v1.2.1 From fb27979e6538e0f7c263b3d9f7400190f762e2fd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Mar 2008 01:13:39 +0100 Subject: Recommit of antonys previous commit. Bug#21413 "Engine table handler used by multiple threads in REPLACE DELAYED" When executing a REPLACE DELAYED statement, the storage engine ::extra() method was invoked by a different thread than the thread which has acquired the handler instance. This did not cause problems within the current server and with the current storage engines. But it has the potential to confuse future storage engines. Added code to avoid surplus calls to extra() method in case of DELAYED which avoids calling storage engine from a different thread than expected. No test case. This change does not change behavior in conjunction with current storage engines. So it cannot be tested by the regression test suite. sql/sql_insert.cc: Bug#21413 When performing DELAYED operations, we should not call the storage engine methods from the 'wrong' context. Ensure that the calls to the methods are appropiately guarded by either moving calls to sections where the lock_type is checked. No need to copy all elements of TABLE_LIST when opening table using open_ltable(). --- sql/sql_insert.cc | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f5bbba742a5..2e371971838 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -315,18 +315,23 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, error=0; id=0; thd->proc_info="update"; - if (duplic != DUP_ERROR || ignore) - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - /* - let's *try* to start bulk inserts. It won't necessary - start them as values_list.elements should be greater than - some - handler dependent - threshold. - So we call start_bulk_insert to perform nesessary checks on - values_list.elements, and - if nothing else - to initialize - the code to make the call of end_bulk_insert() below safe. - */ +#ifndef EMBEDDED_LIBRARY if (lock_type != TL_WRITE_DELAYED) +#endif /* EMBEDDED_LIBRARY */ + { + if (duplic != DUP_ERROR || ignore) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + + /* + let's *try* to start bulk inserts. It won't necessary + start them as values_list.elements should be greater than + some - handler dependent - threshold. + So we call start_bulk_insert to perform nesessary checks on + values_list.elements, and - if nothing else - to initialize + the code to make the call of end_bulk_insert() below safe. + */ table->file->start_bulk_insert(values_list.elements); + } while ((values= its++)) { @@ -415,6 +420,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, else if (table->next_number_field && info.copied) id=table->next_number_field->val_int(); // Return auto_increment value + if (duplic != DUP_ERROR || ignore) + table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + /* Invalidate the table in the query cache if something changed. For the transactional algorithm to work the invalidation must be @@ -455,8 +463,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, table->next_number_field=0; thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->next_insert_id=0; // Reset this if wrongly used - if (duplic != DUP_ERROR || ignore) - table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); /* Reset value of LAST_INSERT_ID if no rows where inserted */ if (!info.copied && thd->insert_id_used) @@ -561,7 +567,12 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(-1); } } - if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) + /* + Only call extra() handler method if we are not performing a DELAYED + operation. It will instead be executed by delayed insert thread. + */ + if ((duplic == DUP_UPDATE || duplic == DUP_REPLACE) && + (insert_table_list->lock_type != TL_WRITE_DELAYED)) table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); DBUG_RETURN(0); @@ -930,9 +941,11 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) my_error(ER_OUT_OF_RESOURCES,MYF(0)); goto err1; } - tmp->table_list= *table_list; // Needed to open table + /* We only need the db and table name to open tables with open_ltable() */ tmp->table_list.db= tmp->thd.db; + tmp->table_list.db_length= table_list->db_length; tmp->table_list.alias= tmp->table_list.real_name=tmp->thd.query; + tmp->table_list.real_name_length= table_list->real_name_length; tmp->lock(); pthread_mutex_lock(&tmp->mutex); if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, @@ -1491,6 +1504,9 @@ bool delayed_insert::handle_inserts(void) info.ignore= row->ignore; info.handle_duplicates= row->dup; + if (info.handle_duplicates == DUP_UPDATE || + info.handle_duplicates == DUP_REPLACE) + table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); if (info.ignore || info.handle_duplicates != DUP_ERROR) { -- cgit v1.2.1 From 9d661efd7f85b4208b9220434a0d5b5f21ac5070 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Mar 2008 19:49:32 +0300 Subject: Bug#27219: Aggregate functions in ORDER BY. Mixing aggregate functions and non-grouping columns is not allowed in the ONLY_FULL_GROUP_BY mode. However in some cases the error wasn't thrown because of insufficient check. In order to check more thoroughly the new algorithm employs a list of outer fields used in a sum function and a SELECT_LEX::full_group_by_flag. Each non-outer field checked to find out whether it's aggregated or not and the current select is marked accordingly. All outer fields that are used under an aggregate function are added to the Item_sum::outer_fields list and later checked by the Item_sum::check_sum_func function. mysql-test/t/group_by.test: Added a test case for the bug#27219: Aggregate functions in ORDER BY. mysql-test/r/group_by.result: Added a test case for the bug#27219: Aggregate functions in ORDER BY. sql/sql_select.cc: Bug#27219: Aggregate functions in ORDER BY. Implementation of new check for mixing non aggregated fields and aggregation function in the ONLY_FULL_GROUP_BY mode. sql/sql_lex.cc: Bug#27219: Aggregate functions in ORDER BY. Initialization of the full_group_by_flag bitmap. SELECT_LEX::test_limit function doesn't reset ORDER BY clause anymore. sql/sql_lex.h: Bug#27219: Aggregate functions in ORDER BY. The full_group_by_flag is added to the SELECT_LEX class. sql/item_sum.h: Bug#27219: Aggregate functions in ORDER BY. The outer_fields list is added to the Item_sum class. sql/mysql_priv.h: Bug#27219: Aggregate functions in ORDER BY. Defined a set of constants used in the new check for mixing non aggregated fields and sum functions in the ONLY_FULL_GROUP_BY_MODE. sql/item_subselect.cc: Bug#27219: Aggregate functions in ORDER BY. The Item_in_subselect::select_in_like_transformer function now drops ORDER BY clause in all selects in a subquery. sql/item_sum.cc: Bug#27219: Aggregate functions in ORDER BY. Now the Item_sum::check_sum_func function now checks whether fields in the outer_fields list are aggregated or not and marks selects accordingly. sql/item.cc: Bug#27219: Aggregate functions in ORDER BY. Now the Item_field::fix_fields function checks whether the field is aggregated or not and marks its select_lex accordingly. --- sql/item.cc | 28 ++++++++++++++++++---- sql/item_subselect.cc | 14 +++++++++++ sql/item_sum.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ sql/item_sum.h | 7 ++++++ sql/mysql_priv.h | 7 ++++++ sql/sql_lex.cc | 3 +-- sql/sql_lex.h | 11 ++++++++- sql/sql_select.cc | 34 ++++----------------------- 8 files changed, 132 insertions(+), 36 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 6f0119393e7..85756dcb124 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3925,9 +3925,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference) } if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) goto error; - else if (!ret) - return FALSE; outer_fixed= TRUE; + if (!ret) + goto mark_non_agg_field; } else if (!from_field) goto error; @@ -3939,9 +3939,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference) int ret; if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) goto error; - else if (!ret) - return FALSE; outer_fixed= 1; + if (!ret) + goto mark_non_agg_field; } /* @@ -4007,6 +4007,26 @@ bool Item_field::fix_fields(THD *thd, Item **reference) thd->lex->current_select->non_agg_fields.push_back(this); marker= thd->lex->current_select->cur_pos_in_select_list; } +mark_non_agg_field: + if (fixed && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) + { + /* + Mark selects according to presence of non aggregated fields. + Fields from outer selects added to the aggregate function + outer_fields list as its unknown at the moment whether it's + aggregated or not. + */ + if (!thd->lex->in_sum_func) + cached_table->select_lex->full_group_by_flag|= NON_AGG_FIELD_USED; + else + { + if (outer_fixed) + thd->lex->in_sum_func->outer_fields.push_back(this); + else if (thd->lex->in_sum_func->nest_level != + thd->lex->current_select->nest_level) + cached_table->select_lex->full_group_by_flag|= NON_AGG_FIELD_USED; + } + } return FALSE; error: diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b3710841dfb..1c81a4ac3a1 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1434,6 +1434,19 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) DBUG_ENTER("Item_in_subselect::select_in_like_transformer"); + { + /* + IN/SOME/ALL/ANY subqueries aren't support LIMIT clause. Without it + ORDER BY clause becomes meaningless thus we drop it here. + */ + SELECT_LEX *sl= current->master_unit()->first_select(); + for (; sl; sl= sl->next_select()) + { + if (sl->join) + sl->join->order= 0; + } + } + if (changed) { DBUG_RETURN(RES_OK); @@ -1468,6 +1481,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) transformed= 1; arena= thd->activate_stmt_arena_if_needed(&backup); + /* Both transformers call fix_fields() only for Items created inside them, and all that items do not make permanent changes in current item arena diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 3d6d46ab3f4..42c934261b0 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -66,6 +66,7 @@ bool Item_sum::init_sum_func_check(THD *thd) aggr_sel= NULL; max_arg_level= -1; max_sum_func_level= -1; + outer_fields.empty(); return FALSE; } @@ -175,6 +176,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) MYF(0)); return TRUE; } + if (in_sum_func) { /* @@ -195,6 +197,68 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); set_if_bigger(in_sum_func->max_sum_func_level, max_sum_func_level); } + + /* + Check that non-aggregated fields and sum functions aren't mixed in the + same select in the ONLY_FULL_GROUP_BY mode. + */ + if (outer_fields.elements) + { + Item_field *field; + /* + Here we compare the nesting level of the select to which an outer field + belongs to with the aggregation level of the sum function. All fields in + the outer_fields list are checked. + + If the nesting level is equal to the aggregation level then the field is + aggregated by this sum function. + If the nesting level is less than the aggregation level then the field + belongs to an outer select. In this case if there is an embedding sum + function add current field to functions outer_fields list. If there is + no embedding function then the current field treated as non aggregated + and the select it belongs to is marked accordingly. + If the nesting level is greater than the aggregation level then it means + that this field was added by an inner sum function. + Consider an example: + + select avg ( <-- we are here, checking outer.f1 + select ( + select sum(outer.f1 + inner.f1) from inner + ) from outer) + from most_outer; + + In this case we check that no aggregate functions are used in the + select the field belongs to. If there are some then an error is + raised. + */ + List_iterator of(outer_fields); + while ((field= of++)) + { + SELECT_LEX *sel= field->cached_table->select_lex; + if (sel->nest_level < aggr_level) + { + if (in_sum_func) + { + /* + Let upper function decide whether this field is a non + aggregated one. + */ + in_sum_func->outer_fields.push_back(field); + } + else + sel->full_group_by_flag|= NON_AGG_FIELD_USED; + } + if (sel->nest_level > aggr_level && + (sel->full_group_by_flag & SUM_FUNC_USED) && + !sel->group_list.elements) + { + my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, + ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); + return TRUE; + } + } + } + aggr_sel->full_group_by_flag|= SUM_FUNC_USED; update_used_tables(); thd->lex->in_sum_func= in_sum_func; return FALSE; diff --git a/sql/item_sum.h b/sql/item_sum.h index bf0abe53eea..d39fc96e254 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -239,6 +239,13 @@ public: int8 max_arg_level; /* max level of unbound column references */ int8 max_sum_func_level;/* max level of aggregation for embedded functions */ bool quick_group; /* If incremental update of fields */ + /* + This list is used by the check for mixing non aggregated fields and + sum functions in the ONLY_FULL_GROUP_BY_MODE. We save all outer fields + directly or indirectly used under this function it as it's unclear + at the moment of fixing outer field whether it's aggregated or not. + */ + List outer_fields; protected: table_map used_tables_cache; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 59ec18e1a3d..6352647a154 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1044,6 +1044,13 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, bool allow_null_cond, int *error); extern Item **not_found_item; +/* + A set of constants used for checking non aggregated fields and sum + functions mixture in the ONLY_FULL_GROUP_BY_MODE. +*/ +#define NON_AGG_FIELD_USED 1 +#define SUM_FUNC_USED 2 + /* This enumeration type is used only by the function find_item_in_list to return the info on how an item has been resolved against a list diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f1b4ffc949d..6bfcd982b04 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1253,6 +1253,7 @@ void st_select_lex::init_select() non_agg_fields.empty(); cond_value= having_value= Item::COND_UNDEF; inner_refs_list.empty(); + full_group_by_flag= 0; } /* @@ -1491,8 +1492,6 @@ bool st_select_lex::test_limit() "LIMIT & IN/ALL/ANY/SOME subquery"); return(1); } - // no sense in ORDER BY without LIMIT - order_list.empty(); return(0); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f216f51b0e4..cde4c3a97b3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -611,7 +611,16 @@ public: joins on the right. */ List *prev_join_using; - + /* + Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate + functions and non aggregated fields when GROUP BY list is absent. + Bits: + 0 - non aggregated fields are used in this select, + defined as NON_AGG_FIELD_USED. + 1 - aggregate functions are used in this select, + defined as SUM_FUNC_USED. + */ + uint8 full_group_by_flag; void init_query(); void init_select(); st_select_lex_unit* master_unit(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6392f7c4299..8c5d09f4e16 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -568,37 +568,13 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check if there are references to un-aggregated columns when computing aggregate functions with implicit grouping (there is no GROUP BY). - TODO: Add check of calculation of GROUP functions and fields: - SELECT COUNT(*)+table.col1 from table1; */ - if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) + if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list && + select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED)) { - if (!group_list) - { - uint flag=0; - List_iterator_fast it(fields_list); - Item *item; - while ((item= it++)) - { - if (item->with_sum_func) - flag|=1; - else if (!(flag & 2) && !item->const_during_execution()) - flag|=2; - } - if (having) - { - if (having->with_sum_func) - flag |= 1; - else if (!having->const_during_execution()) - flag |= 2; - } - if (flag == 3) - { - my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, - ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); - DBUG_RETURN(-1); - } - } + my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, + ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); + DBUG_RETURN(-1); } { /* Caclulate the number of groups */ -- cgit v1.2.1 From 4ec65151dc8e1b30b05a84c2f3a8bd2b9ce641c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Mar 2008 18:59:13 +0300 Subject: Fix for Bug#35469: server crash with LOAD DATA INFILE to a VIEW. The problem was that LOAD DATA code (sql_load.cc) didn't take into account that there may be items, representing references to other columns. This is a usual case in views. The crash happened because Item_direct_view_ref was casted to Item_user_var_as_out_param, which is not a base class. The fix is to 1) Handle references properly; 2) Ensure that an item is treated as a user variable only when it is a user variable indeed; 3) Report an error if LOAD DATA is used to load data into non-updatable column. mysql-test/r/loaddata.result: Update result file. mysql-test/t/loaddata.test: Add a test case form Bug#35469: server crash with LOAD DATA INFILE to a VIEW. sql/share/errmsg.txt: Introduce a new error. sql/sql_load.cc: Handle reference-items properly. mysql-test/std_data/bug35649.data: Add a data file for the test case. --- sql/share/errmsg.txt | 4 ++++ sql/sql_load.cc | 56 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 9e6cf462113..a3514776d6e 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5641,3 +5641,7 @@ ER_NAME_BECOMES_EMPTY eng "Name '%-.64s' has become ''" ER_AMBIGUOUS_FIELD_TERM eng "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY" + +ER_LOAD_DATA_INVALID_COLUMN + eng "Invalid column reference (%-.64s) in LOAD DATA" + diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 4da3c19bb3c..e9fd04dff15 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -233,9 +233,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, while ((item= it++)) { - if (item->type() == Item::FIELD_ITEM) + Item *real_item= item->real_item(); + + if (real_item->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field*)item)->field; + Field *field= ((Item_field*)real_item)->field; if (field->flags & BLOB_FLAG) { use_blobs= 1; @@ -244,7 +246,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, else tot_length+= field->field_length; } - else + else if (item->type() == Item::STRING_ITEM) use_vars= 1; } if (use_blobs && !ex->line_term->length() && !field_term->length()) @@ -705,6 +707,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, { uint length; byte *pos; + Item *real_item; if (read_info.read_field()) break; @@ -716,14 +719,17 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, pos=read_info.row_start; length=(uint) (read_info.row_end-pos); + real_item= item->real_item(); + if (!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos, STRING_WITH_LEN("NULL"))) || (length == 1 && read_info.found_null)) { - if (item->type() == Item::FIELD_ITEM) + + if (real_item->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field *)item)->field; + Field *field= ((Item_field *)real_item)->field; if (field->reset()) { my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name, @@ -740,25 +746,39 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER_WARN_NULL_TO_NOTNULL, 1); } } - else + else if (item->type() == Item::STRING_ITEM) + { ((Item_user_var_as_out_param *)item)->set_null_value( read_info.read_charset); + } + else + { + my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); + DBUG_RETURN(1); + } + continue; } - if (item->type() == Item::FIELD_ITEM) + if (real_item->type() == Item::FIELD_ITEM) { - - Field *field= ((Item_field *)item)->field; + Field *field= ((Item_field *)real_item)->field; field->set_notnull(); read_info.row_end[0]=0; // Safe to change end marker if (field == table->next_number_field) table->auto_increment_field_not_null= TRUE; field->store((char*) pos, length, read_info.read_charset); } - else + else if (item->type() == Item::STRING_ITEM) + { ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length, - read_info.read_charset); + read_info.read_charset); + } + else + { + my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); + DBUG_RETURN(1); + } } if (read_info.error) break; @@ -774,9 +794,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, break; for (; item ; item= it++) { - if (item->type() == Item::FIELD_ITEM) + Item *real_item= item->real_item(); + if (real_item->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field *)item)->field; + Field *field= ((Item_field *)real_item)->field; if (field->reset()) { my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name, @@ -796,9 +817,16 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER_WARN_TOO_FEW_RECORDS, ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count); } - else + else if (item->type() == Item::STRING_ITEM) + { ((Item_user_var_as_out_param *)item)->set_null_value( read_info.read_charset); + } + else + { + my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); + DBUG_RETURN(1); + } } } -- cgit v1.2.1 From a9089cf460c7d7be3d8b843c948f0c707822878e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Mar 2008 14:02:27 -0400 Subject: Bug#26243 mysql command line crash after control-c - Backported the 5.1 DBUG to 5.0. - Avoid memory cleanup race on Windows client for CTRL-C client/mysql.cc: Bug#26243 mysql command line crash after control-c - On Windows, the sigint handler shouldn't call mysql_end because the main thread will do so automatically. - Remove unnecessary signal call from the sigint handler. - Call my_end with proper value. dbug/dbug.c: Bug#26243 mysql command line crash after control-c - Backported the 5.1 DBUG library. The old version uses a non-thread safe global variable 'static struct state *stack'. dbug/factorial.c: Bug#26243 mysql command line crash after control-c - Backported the 5.1 DBUG library. The old version uses a non-thread safe global variable 'static struct state *stack'. dbug/user.r: Bug#26243 mysql command line crash after control-c - Backported the 5.1 DBUG library. The old version uses a non-thread safe global variable 'static struct state *stack'. include/my_dbug.h: Bug#26243 mysql command line crash after control-c - Backported the 5.1 DBUG library. The old version uses a non-thread safe global variable 'static struct state *stack'. libmysql/libmysql.c: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. myisam/mi_open.c: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/ha_federated.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/ha_innodb.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/ha_myisammrg.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/item_cmpfunc.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/mysqld.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/net_serv.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/opt_range.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/set_var.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/slave.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/sql_cache.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. sql/sql_select.cc: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. tests/mysql_client_test.c: Bug#26243 mysql command line crash after control-c - Update for new DBUG library. --- sql/ha_federated.cc | 2 +- sql/ha_innodb.cc | 2 +- sql/ha_myisammrg.cc | 2 +- sql/item_cmpfunc.cc | 2 +- sql/mysqld.cc | 13 ++++--------- sql/net_serv.cc | 4 ++-- sql/opt_range.cc | 6 +----- sql/set_var.cc | 2 +- sql/slave.cc | 2 +- sql/sql_cache.cc | 6 +++--- sql/sql_select.cc | 2 +- 11 files changed, 17 insertions(+), 26 deletions(-) (limited to 'sql') diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index ac1e0962ffb..35648ea19c7 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1088,7 +1088,7 @@ bool ha_federated::create_where_from_key(String *to, uint store_length= key_part->store_length; uint part_length= min(store_length, length); needs_quotes= 1; - DBUG_DUMP("key, start of loop", (char *) ptr, length); + DBUG_DUMP("key, start of loop", ptr, length); if (key_part->null_bit) { diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 2d2007c8fdd..a2de8ea1d0b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4250,7 +4250,7 @@ ha_innobase::rnd_pos( int error; uint keynr = active_index; DBUG_ENTER("rnd_pos"); - DBUG_DUMP("key", (char*) pos, ref_length); + DBUG_DUMP("key", pos, ref_length); statistic_increment(current_thd->status_var.ha_read_rnd_count, &LOCK_status); diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 78492d2843d..02d0eaf2af3 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -126,7 +126,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno)); return (my_errno ? my_errno : -1); } - DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc...")) + DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc...")); myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref); if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED || test_if_locked == HA_OPEN_ABORT_IF_LOCKED)) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 17345e76bba..16f3e51d615 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4130,7 +4130,7 @@ longlong Item_is_not_null_test::val_int() } if (args[0]->is_null()) { - DBUG_PRINT("info", ("null")) + DBUG_PRINT("info", ("null")); owner->was_null|= 1; DBUG_RETURN(0); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b8df51e9e58..b8f675ff696 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1071,12 +1071,9 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) extern "C" sig_handler print_signal_warning(int sig) { - if (!DBUG_IN_USE) - { - if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %ld", - sig, my_thread_id()); - } + if (global_system_variables.log_warnings) + sql_print_warning("Got signal %d from thread %ld", + sig, my_thread_id()); #ifdef DONT_REMEMBER_SIGNAL my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif @@ -1718,7 +1715,7 @@ void end_thread(THD *thd, bool put_in_cache) ! abort_loop && !kill_cached_threads) { /* Don't kill the thread, just put it in cache for reuse */ - DBUG_PRINT("info", ("Adding thread to cache")) + DBUG_PRINT("info", ("Adding thread to cache")); cached_thread_count++; while (!abort_loop && ! wake_thread && ! kill_cached_threads) (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count); @@ -3623,8 +3620,6 @@ int main(int argc, char **argv) MY_INIT(argv[0]); // init my_sys library & pthreads /* ^^^ Nothing should be before this line! */ - DEBUGGER_OFF; - /* Set signal used to kill MySQL */ #if defined(SIGUSR2) thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 017a2eb9ecd..a40764577fd 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -394,7 +394,7 @@ my_net_write(NET *net,const char *packet,ulong len) if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) return 1; #ifndef DEBUG_DATA_PACKETS - DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE); + DBUG_DUMP("packet_header", buff, NET_HEADER_SIZE); #endif return test(net_write_buff(net,packet,len)); } @@ -892,7 +892,7 @@ my_real_read(NET *net, ulong *complen) if (i == 0) { /* First parts is packet length */ ulong helping; - DBUG_DUMP("packet_header",(char*) net->buff+net->where_b, + DBUG_DUMP("packet_header", net->buff+net->where_b, NET_HEADER_SIZE); if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c3eddbd0abf..17a4701b515 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -9570,8 +9570,6 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, int idx; char buff[1024]; DBUG_ENTER("print_sel_tree"); - if (! _db_on_) - DBUG_VOID_RETURN; String tmp(buff,sizeof(buff),&my_charset_bin); tmp.length(0); @@ -9601,8 +9599,6 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, struct st_ror_scan_info **end) { DBUG_ENTER("print_ror_scans"); - if (! _db_on_) - DBUG_VOID_RETURN; char buff[1024]; String tmp(buff,sizeof(buff),&my_charset_bin); @@ -9665,7 +9661,7 @@ static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg) { char buf[MAX_KEY/8+1]; DBUG_ENTER("print_quick"); - if (! _db_on_ || !quick) + if (!quick) DBUG_VOID_RETURN; DBUG_LOCK_FILE; diff --git a/sql/set_var.cc b/sql/set_var.cc index a99b063a97e..84766e511ca 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1990,7 +1990,7 @@ void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type, { DATE_TIME_FORMAT *old; DBUG_ENTER("sys_var_date_time_format::update2"); - DBUG_DUMP("positions",(char*) new_value->positions, + DBUG_DUMP("positions", new_value->positions, sizeof(new_value->positions)); if (type == OPT_GLOBAL) diff --git a/sql/slave.cc b/sql/slave.cc index 8a3620080f2..2cd4b00cca9 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3339,7 +3339,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) } DBUG_PRINT("info", ("thd->options: %s", - (thd->options & OPTION_BEGIN) ? "OPTION_BEGIN" : "")) + (thd->options & OPTION_BEGIN) ? "OPTION_BEGIN" : "")); /* Protect against common user error of setting the counter to 1 diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 8c868971911..f8906a17c12 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -315,13 +315,13 @@ TODO list: #define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\ (ulong)(M))); pthread_mutex_unlock(M);} #define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \ - if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")) \ + if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); } #define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \ - if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")) \ + if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); } #define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \ - if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")) \ + if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \ else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); } #define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \ pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));} diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6392f7c4299..ef3abb06b1e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14470,7 +14470,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, ifield->db_name= iref->db_name; } #ifndef DBUG_OFF - if (_db_on_ && !item_field->name) + if (!item_field->name) { char buff[256]; String str(buff,sizeof(buff),&my_charset_bin); -- cgit v1.2.1 From 18a01ce9246616e2a3f131d69c132109335c9359 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Mar 2008 09:52:16 +0200 Subject: fixed warnings and compile errors from the fix for bug 26243 --- sql/ha_federated.cc | 2 +- sql/ha_innodb.cc | 2 +- sql/ha_ndbcluster.cc | 34 ++++++++++++++++------------------ sql/ha_ndbcluster_cond.cc | 2 +- 4 files changed, 19 insertions(+), 21 deletions(-) (limited to 'sql') diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 7a7d65a3d34..2ccfeba74cb 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1095,7 +1095,7 @@ bool ha_federated::create_where_from_key(String *to, uint store_length= key_part->store_length; uint part_length= min(store_length, length); needs_quotes= 1; - DBUG_DUMP("key, start of loop", ptr, length); + DBUG_DUMP("key, start of loop", (uchar *)ptr, length); if (key_part->null_bit) { diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a2de8ea1d0b..1be6137460b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4250,7 +4250,7 @@ ha_innobase::rnd_pos( int error; uint keynr = active_index; DBUG_ENTER("rnd_pos"); - DBUG_DUMP("key", pos, ref_length); + DBUG_DUMP("key", (uchar *)pos, ref_length); statistic_increment(current_thd->status_var.ha_read_rnd_count, &LOCK_status); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index e3ab2b67e26..0a75b328ca0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -677,7 +677,7 @@ int ha_ndbcluster::set_ndb_key(NdbOperation *ndb_op, Field *field, DBUG_PRINT("enter", ("%d: %s, ndb_type: %u, len=%d", fieldnr, field->field_name, field->type(), pack_len)); - DBUG_DUMP("key", (char*)field_ptr, pack_len); + DBUG_DUMP("key", (uchar*)field_ptr, pack_len); DBUG_ASSERT(ndb_supported_type(field->type())); DBUG_ASSERT(! (field->flags & BLOB_FLAG)); @@ -699,7 +699,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, DBUG_PRINT("enter", ("%d: %s, type: %u, len=%d, is_null=%s", fieldnr, field->field_name, field->type(), pack_len, field->is_null()?"Y":"N")); - DBUG_DUMP("value", (char*) field_ptr, pack_len); + DBUG_DUMP("value", (uchar*) field_ptr, pack_len); DBUG_ASSERT(ndb_supported_type(field->type())); { @@ -737,7 +737,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, // Set value to NULL DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0)); DBUG_PRINT("info", ("bit field")); - DBUG_DUMP("value", (char*)&bits, pack_len); + DBUG_DUMP("value", (uchar*)&bits, pack_len); #ifdef WORDS_BIGENDIAN /* store lsw first */ bits = ((bits >> 32) & 0x00000000FFFFFFFFLL) @@ -768,7 +768,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, DBUG_PRINT("value", ("set blob ptr: %p len: %u", blob_ptr, blob_len)); - DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26)); + DBUG_DUMP("value", (uchar*)blob_ptr, min(blob_len, 26)); if (set_blob_value) *set_blob_value= TRUE; @@ -1007,8 +1007,8 @@ int ha_ndbcluster::get_metadata(const char *path) ("metadata, pack_length: %d getFrmLength: %d memcmp: %d", pack_length, tab->getFrmLength(), memcmp(pack_data, tab->getFrmData(), pack_length))); - DBUG_DUMP("pack_data", (char*)pack_data, pack_length); - DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength()); + DBUG_DUMP("pack_data", (uchar*)pack_data, pack_length); + DBUG_DUMP("frm", (uchar*)tab->getFrmData(), tab->getFrmLength()); error= 3; invalidating_ndb_table= FALSE; } @@ -1502,7 +1502,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf) int res; DBUG_ENTER("pk_read"); DBUG_PRINT("enter", ("key_len: %u", key_len)); - DBUG_DUMP("key", (char*)key, key_len); + DBUG_DUMP("key", (uchar*)key, key_len); NdbOperation::LockMode lm= (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); @@ -1514,7 +1514,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf) { // This table has no primary key, use "hidden" primary key DBUG_PRINT("info", ("Using hidden key")); - DBUG_DUMP("key", (char*)key, 8); + DBUG_DUMP("key", (uchar*)key, 8); if (set_hidden_key(op, no_fields, key)) ERR_RETURN(trans->getNdbError()); @@ -1797,7 +1797,7 @@ int ha_ndbcluster::unique_index_read(const byte *key, NdbIndexOperation *op; DBUG_ENTER("ha_ndbcluster::unique_index_read"); DBUG_PRINT("enter", ("key_len: %u, index: %u", key_len, active_index)); - DBUG_DUMP("key", (char*)key, key_len); + DBUG_DUMP("key", (uchar*)key, key_len); NdbOperation::LockMode lm= (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); @@ -2126,7 +2126,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, { DBUG_PRINT("info", ("key %d:%d offset=%d length=%d last=%d bound=%d", j, i, tot_len, part_len, p.part_last, p.bound_type)); - DBUG_DUMP("info", (const char*)p.part_ptr, part_store_len); + DBUG_DUMP("info", (const uchar*)p.part_ptr, part_store_len); // Set bound if not cancelled via type -1 if (p.bound_type != -1) @@ -2644,7 +2644,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) // Require that the PK for this record has previously been // read into m_ref - DBUG_DUMP("key", m_ref, NDB_HIDDEN_PRIMARY_KEY_LENGTH); + DBUG_DUMP("key", (uchar *)m_ref, NDB_HIDDEN_PRIMARY_KEY_LENGTH); if (set_hidden_key(op, table->s->fields, m_ref)) ERR_RETURN(op->getNdbError()); @@ -2864,8 +2864,6 @@ void ha_ndbcluster::print_results() DBUG_ENTER("print_results"); #ifndef DBUG_OFF - if (!_db_on_) - DBUG_VOID_RETURN; char buf_type[MAX_FIELD_WIDTH], buf_val[MAX_FIELD_WIDTH]; String type(buf_type, sizeof(buf_type), &my_charset_bin); @@ -3341,7 +3339,7 @@ void ha_ndbcluster::position(const byte *record) memcpy(ref, m_ref, ref_length); } - DBUG_DUMP("ref", (char*)ref, ref_length); + DBUG_DUMP("ref", (uchar*)ref, ref_length); DBUG_VOID_RETURN; } @@ -6132,14 +6130,14 @@ ha_ndbcluster::register_query_cache_table(THD *thd, if (!is_autocommit) { - DBUG_PRINT("exit", ("Can't register table during transaction")) + DBUG_PRINT("exit", ("Can't register table during transaction")); DBUG_RETURN(FALSE); } if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count)) { *engine_data= 0; - DBUG_PRINT("exit", ("Error, could not get commitcount")) + DBUG_PRINT("exit", ("Error, could not get commitcount")); DBUG_RETURN(FALSE); } *engine_data= commit_count; @@ -6263,7 +6261,7 @@ static int packfrm(const void *data, uint len, } DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len)); - DBUG_DUMP("compressed", (char*)data, org_len); + DBUG_DUMP("compressed", (uchar*)data, org_len); error= 2; blob_len= sizeof(frm_blob_struct::frm_blob_header)+org_len; @@ -6307,7 +6305,7 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len, DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu", ver,complen,orglen)); - DBUG_DUMP("blob->data", (char*) blob->data, complen); + DBUG_DUMP("blob->data", (uchar*) blob->data, complen); if (ver != 1) { diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index f5b41959b40..37e710acff4 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -1419,7 +1419,7 @@ int ha_ndbcluster_cond::generate_scan_filter_from_key(NdbScanOperation *op, uint32 pack_len= field->pack_length(); const byte* ptr= key; DBUG_PRINT("info", ("Filtering value for %s", field->field_name)); - DBUG_DUMP("key", (char*)ptr, pack_len); + DBUG_DUMP("key", (uchar*)ptr, pack_len); if (key_part->null_bit) { DBUG_PRINT("info", ("Generating ISNULL filter")); -- cgit v1.2.1 From 8ae5aa3bd81124ed4d3c7e74139b028fd091cefc Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Mar 2008 16:12:23 +0200 Subject: fixes for warnings and compile errors for the fix of bug 26243 --- sql/ha_berkeley.cc | 8 ++++---- sql/mysqld.cc | 2 +- sql/sql_union.cc | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index fbfd5031656..1de40db2724 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -467,7 +467,7 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key) KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts; uint key_length=new_key->size; - DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size); + DBUG_DUMP("key_in_index", (uchar *)saved_key_ptr, saved_key->size); for (; key_part != end && (int) key_length > 0; key_part++) { int cmp; @@ -903,7 +903,7 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff, key_length-=key_part->length; } key->size= (u_int32_t) (buff - (char*) key->data); - DBUG_DUMP("key",(char*) key->data, key->size); + DBUG_DUMP("key",(uchar*) key->data, key->size); DBUG_RETURN(key); } @@ -947,7 +947,7 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, key_length-=key_part->store_length; } key->size= (u_int32_t) (buff - (char*) key->data); - DBUG_DUMP("key",(char*) key->data, key->size); + DBUG_DUMP("key",(uchar*) key->data, key->size); DBUG_RETURN(key); } @@ -1705,7 +1705,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos) pos+=key_part->field->packed_col_length((char*) pos,key_part->length); to->size= (uint) (pos- (byte*) to->data); } - DBUG_DUMP("key", (char*) to->data, to->size); + DBUG_DUMP("key", (uchar*) to->data, to->size); return to; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b8f675ff696..c239530f2fc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6943,7 +6943,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), switch(optid) { case '#': #ifndef DBUG_OFF - DBUG_PUSH(argument ? argument : default_dbug_option); + DBUG_SET_INITIAL(argument ? argument : default_dbug_option); #endif opt_endinfo=1; /* unireg: memory allocation */ break; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 25a0540e4dd..da5e118b069 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -444,7 +444,9 @@ bool st_select_lex_unit::exec() } /* re-enabling indexes for next subselect iteration */ if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL)) + { DBUG_ASSERT(0); + } } for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select()) { -- cgit v1.2.1 From 11714e6842f906901ac8e3ff9ac003ae0058fce7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Mar 2008 17:50:46 +0200 Subject: fixed warnings from the fix of 26243 --- sql/examples/ha_tina.cc | 2 +- sql/item_func.cc | 2 +- sql/lock.cc | 2 +- sql/sql_analyse.cc | 24 ++++++++++++------------ 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'sql') diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc index 0d1d821cf17..0b57fe86e62 100644 --- a/sql/examples/ha_tina.cc +++ b/sql/examples/ha_tina.cc @@ -883,7 +883,7 @@ int ha_tina::delete_all_rows() DBUG_ENTER("ha_tina::delete_all_rows"); if (!records_is_known) - return (my_errno=HA_ERR_WRONG_COMMAND); + DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND); /* Invalidate all cached mmap pages */ if (free_mmap(share)) diff --git a/sql/item_func.cc b/sql/item_func.cc index a6fb8a94b69..7416471d630 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5115,7 +5115,7 @@ double Item_func_match::val_real() DBUG_RETURN(-1.0); if (key != NO_SUCH_KEY && table->null_row) /* NULL row from an outer join */ - return 0.0; + DBUG_RETURN(0.0); if (join_key) { diff --git a/sql/lock.cc b/sql/lock.cc index cf06be5f95f..47458702033 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -703,7 +703,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, { my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table_ptr[i]->s->db, table_ptr[i]->s->table_name); - return 0; + DBUG_RETURN(0); } } diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 2e90d00f8aa..4b3264069b5 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -195,13 +195,13 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) */ for (; str != end && my_isspace(system_charset_info, *str); str++) ; if (str == end) - return 0; + DBUG_RETURN(0); if (*str == '-') { info->negative = 1; if (++str == end || *str == '0') // converting -0 to a number - return 0; // might lose information + DBUG_RETURN(0); // might lose information } else info->negative = 0; @@ -219,33 +219,33 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) int error; info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error); if (info->integers == 1) - return 0; // a single number can't be zerofill + DBUG_RETURN(0); // a single number can't be zerofill info->maybe_zerofill = 1; - return 1; // a zerofill number, or an integer + DBUG_RETURN(1); // a zerofill number, or an integer } if (*str == '.' || *str == 'e' || *str == 'E') { if (info->zerofill) // can't be zerofill anymore - return 0; + DBUG_RETURN(0); if ((str + 1) == end) // number was something like '123[.eE]' { char *endpos= (char*) str; int error; info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error); - return 1; + DBUG_RETURN(1); } if (*str == 'e' || *str == 'E') // number may be something like '1e+50' { str++; if (*str != '-' && *str != '+') - return 0; + DBUG_RETURN(0); for (str++; str != end && my_isdigit(system_charset_info,*str); str++) ; if (str == end) { info->is_float = 1; // we can't use variable decimals here - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } for (str++; *(end - 1) == '0'; end--); // jump over zeros at the end if (str == end) // number was something like '123.000' @@ -253,17 +253,17 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) char *endpos= (char*) str; int error; info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error); - return 1; + DBUG_RETURN(1); } for (; str != end && my_isdigit(system_charset_info,*str); str++) info->decimals++; if (str == end) { info->dval = my_atof(begin); - return 1; + DBUG_RETURN(1); } } - return 0; + DBUG_RETURN(0); } -- cgit v1.2.1 From 6edab4bc081b29894f3eaf70468d989ea956ff18 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 30 Mar 2008 15:46:37 -0400 Subject: Bug#26243 - Cleanup Valgrind error --- sql/tztime.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/tztime.cc b/sql/tztime.cc index bedbf921cae..b7381e2ed95 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2278,7 +2278,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_ENTER("my_tz_find"); DBUG_PRINT("enter", ("time zone name='%s'", - name ? ((String *)name)->c_ptr() : "NULL")); + name ? ((String *)name)->c_ptr_safe() : "NULL")); DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread); -- cgit v1.2.1 From 90112d1175b1043850f50cfae2088dc143e4c62e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2008 11:32:00 -0400 Subject: Bug#26294: library name conflict between MySQL 4.x, 5.0 and Qt 3.3 When linking with some external programs, "multiple definition of `init_time'" Rename init_time() to my_init_time() to avoid collision with other libraries (particularly libmng). client/mysqlbinlog.cc: Rename init_time() to my_init_time(). include/my_time.h: Rename init_time() to my_init_time(). sql-common/my_time.c: Rename init_time() to my_init_time(). sql/init.cc: Rename init_time() to my_init_time(). sql/tztime.cc: Rename init_time() to my_init_time(). --- sql/init.cc | 2 +- sql/tztime.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/init.cc b/sql/init.cc index b3b68926683..2dd2031cdaa 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -30,7 +30,7 @@ void unireg_init(ulong options) wild_many='%'; wild_one='_'; wild_prefix='\\'; /* Change to sql syntax */ current_pid=(ulong) getpid(); /* Save for later ref */ - init_time(); /* Init time-functions (read zone) */ + my_init_time(); /* Init time-functions (read zone) */ #ifndef EMBEDDED_LIBRARY my_abort_hook=unireg_abort; /* Abort with close of databases */ #endif diff --git a/sql/tztime.cc b/sql/tztime.cc index bedbf921cae..2b951c4b061 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1035,7 +1035,7 @@ public: return lowest possible my_time_t in case of ambiguity or if we provide time corresponding to the time-gap. - You should call init_time() function before using this function. + You should call my_init_time() function before using this function. RETURN VALUE Corresponding my_time_t value or 0 in case of error @@ -2757,7 +2757,7 @@ main(int argc, char **argv) } printf("gmt_sec_to_TIME = localtime for time_t in [1000000000,1100000000) range\n"); - init_time(); + my_init_time(); /* Be careful here! my_system_gmt_sec doesn't fully handle unnormalized -- cgit v1.2.1 From 2bc7179d2d0019fd2b4666de0990faf3f19b9582 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Apr 2008 12:27:30 -0400 Subject: Follow-up to B-g#15776, test failures on 64-bit linux. Make maximum blob size to be 2**32-1, regardless of word size. Fix failure of timestamp with size of 2**31-1. The method of rounding up to the nearest even number would overflow. mysql-test/r/type_blob.result: 2**32-1 is not a special case for timestamp. Test 2**32-1 and 2**64 as the reliable test points for both 32- and 64-bit machines. I'd like to test 2**32, but that would make tests that vary between architectures. I'd like to generalize the tests by pulling the max blob size from the server, and then "eval"ing N-1, N, and N+1 instead of all these literal numbers, but I have not found a way to get UINT_MAX. mysql-test/t/type_blob.test: 2**32-1 is not a special case for timestamp. Test 2**32-1 and 2**64 as the reliable test points for both 32- and 64-bit machines. I'd like to test 2**32, but that would make tests that vary between architectures. I'd like to generalize the tests by pulling the max blob size from the server, and then "eval"ing N-1, N, and N+1 instead of all these literal numbers, but I have not found a way to get UINT_MAX. sql/field.cc: Fix a bug where the round-to-even code for TIMESTAMP fields failed where the size would overflow the size to zero and then fail. Also, since we silently truncate the size of TIMESTAMP fields, set the maximum size we report is allowable to be the largest parsable number. sql/unireg.h: Make BLOB size the maximum that the packed value in field_blob::get_length() allows. --- sql/field.cc | 24 +++++++++++++++++------- sql/unireg.h | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 2950f349580..99b61ec1ee0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6848,6 +6848,7 @@ uint32 Field_blob::get_length(const char *pos) return (uint32) tmp; } } + /* When expanding this, see also MAX_FIELD_BLOBLENGTH. */ return 0; // Impossible } @@ -8395,11 +8396,11 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, (fld_type_modifier & NOT_NULL_FLAG) && fld_type != FIELD_TYPE_TIMESTAMP) flags|= NO_DEFAULT_VALUE_FLAG; - if (fld_length != 0) + if (fld_length != NULL) { errno= 0; length= strtoul(fld_length, NULL, 10); - if (errno != 0) + if ((errno != 0) || (length > MAX_FIELD_BLOBLENGTH)) { my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH); DBUG_RETURN(TRUE); @@ -8556,7 +8557,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, } break; case FIELD_TYPE_TIMESTAMP: - if (!fld_length) + if (fld_length == NULL) { /* Compressed date YYYYMMDDHHMMSS */ length= MAX_DATETIME_COMPRESSED_WIDTH; @@ -8565,12 +8566,21 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, { /* We support only even TIMESTAMP lengths less or equal than 14 - and 19 as length of 4.1 compatible representation. + and 19 as length of 4.1 compatible representation. Silently + shrink it to MAX_DATETIME_COMPRESSED_WIDTH. */ - length= ((length+1)/2)*2; /* purecov: inspected */ - length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */ + DBUG_ASSERT(MAX_DATETIME_COMPRESSED_WIDTH < UINT_MAX); + if (length != UINT_MAX) /* avoid overflow; is safe because of min() */ + length= ((length+1)/2)*2; + length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); } flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; + /* + Since we silently rewrite down to MAX_DATETIME_COMPRESSED_WIDTH bytes, + the parser should not raise errors unless bizzarely large. + */ + max_field_charlength= UINT_MAX; + if (fld_default_value) { /* Grammar allows only NOW() value for ON UPDATE clause */ @@ -8677,7 +8687,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, ((length > max_field_charlength && fld_type != FIELD_TYPE_SET && fld_type != FIELD_TYPE_ENUM && (fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) || - (!length && + ((length == 0) && fld_type != MYSQL_TYPE_STRING && fld_type != MYSQL_TYPE_VARCHAR && fld_type != FIELD_TYPE_GEOMETRY))) { diff --git a/sql/unireg.h b/sql/unireg.h index 0ab2a40048b..24e57b4e584 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -60,7 +60,7 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 #define MAX_FIELD_VARCHARLENGTH 65535 -#define MAX_FIELD_BLOBLENGTH UINT_MAX +#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */ /* Max column width +1 */ -- cgit v1.2.1 From 57784eae1235d62831cbdab16827027288dd7cbf Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Apr 2008 15:55:37 -0400 Subject: Fix mismerge. sql/field.cc: Fix indentation of new line. --- sql/field.cc | 2 +- sql/item_create.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 91f356988e4..18bb7153060 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8615,7 +8615,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, and 19 as length of 4.1 compatible representation. Silently shrink it to MAX_DATETIME_COMPRESSED_WIDTH. */ - DBUG_ASSERT(MAX_DATETIME_COMPRESSED_WIDTH < UINT_MAX); + DBUG_ASSERT(MAX_DATETIME_COMPRESSED_WIDTH < UINT_MAX); if (length != UINT_MAX) /* avoid overflow; is safe because of min() */ length= ((length+1)/2)*2; length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); diff --git a/sql/item_create.cc b/sql/item_create.cc index 6f3608b6b9a..c897b7aef79 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -531,7 +531,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, ulong decoded_size; errno= 0; decoded_size= strtoul(c_len, NULL, 10); - if (errno != 0) + if ((errno != 0) || (decoded_size > MAX_FIELD_BLOBLENGTH)) { my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH); return NULL; -- cgit v1.2.1 From 1c1f0a62e1f68fd39ae7440042699faaffaaf7fe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Apr 2008 02:53:12 +0400 Subject: BUG#36139 "float, zerofill, crash with subquery" - Make convert_zerofill_number_to_string() take into account that the constant it is converting may evaluate to NULL. mysql-test/r/subselect.result: BUG#36139 "float, zerofill, crash with subquery" - Testcase mysql-test/t/subselect.test: BUG#36139 "float, zerofill, crash with subquery" - Testcase --- sql/item.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 553ba1b152c..9ff1f8c0084 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4156,9 +4156,14 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field) String tmp(buff,sizeof(buff), field->charset()), *res; res= (*item)->val_str(&tmp); - field->prepend_zeros(res); - pos= (char *) sql_strmake (res->ptr(), res->length()); - *item= new Item_string(pos, res->length(), field->charset()); + if ((*item)->is_null()) + *item= new Item_null(); + else + { + field->prepend_zeros(res); + pos= (char *) sql_strmake (res->ptr(), res->length()); + *item= new Item_string(pos, res->length(), field->charset()); + } } -- cgit v1.2.1 From 73f7de59c2739a66dcf1a7d1d4c89a1e19fddcd1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2008 02:27:23 +0500 Subject: Fixed bug#36005: server crashes inside NOT IN clause subquery with impossible WHERE/HAVING clause (subselect_single_select_engine::exec). Allocation and initialization of joined table list t1, t2... of subqueries like: NOT IN (SELECT ... FROM t1,t2,... WHERE 0) is optimized out, however server tries to traverse this list. mysql-test/r/subselect3.result: Added test case for bug#36005. mysql-test/t/subselect3.test: Added test case for bug#36005. sql/sql_select.cc: Fixed bug#36005. 1. JOIN::prepare initializes JOIN::table counter (actually a size of the JOIN::join_tab array) and sets it to a number of joined tables. 2. The make_join_statistics function (when called from JOIN::optimize) allocates and fills the JOIN::join_tab array. However, when optimizing subselect has impossible (definite false) WHERE or HAVING clause, optimizer skips call to make_join_statistics and leaves JOIN::join_tab == NULL. 3. subselect_single_select_engine::exec does traversal of the JOIN::join_tab array and the server dies because array is not allocated but array counter is greater than 0. The JOIN::optimize method has been modified to reset the JOIN::table counter to 0 in cause of impossible WHERE/HAVING clause. --- sql/sql_select.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 976d7322f56..11062998e6a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -832,6 +832,7 @@ JOIN::optimize() "Impossible HAVING" : "Impossible WHERE")); zero_result_cause= having_value == Item::COND_FALSE ? "Impossible HAVING" : "Impossible WHERE"; + tables= 0; error= 0; DBUG_RETURN(0); } -- cgit v1.2.1 From 89b866e7bfc8965046626844ee22ecd5b4e5a774 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2008 00:39:37 +0400 Subject: Bug#36023: Incorrect handling of zero length caused an assertion to fail. When a zero length is provided to the my_decimal_length_to_precision function along with unsigned_flag set to false it returns a negative value. For queries that employs temporary tables may cause failed assertion or excessive memory consumption while temporary table creation. Now the my_decimal_length_to_precision and the my_decimal_precision_to_length functions take unsigned_flag into account only if the length/precision argument is non-zero. mysql-test/t/type_decimal.test: Added a test case for the bug#36023: Incorrect handling of zero length caused an assertion to fail. mysql-test/r/type_decimal.result: Added a test case for the bug#36023: Incorrect handling of zero length caused an assertion to fail. sql/my_decimal.h: Bug#36023: Incorrect handling of zero length caused an assertion to fail. Now the my_decimal_length_to_precision and the my_decimal_precision_to_length functions take unsigned_flag into account only if the length/precision argument is non-zero. --- sql/my_decimal.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/my_decimal.h b/sql/my_decimal.h index c661579ea66..6a0d05921ec 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -164,14 +164,23 @@ inline int check_result_and_overflow(uint mask, int result, my_decimal *val) inline uint my_decimal_length_to_precision(uint length, uint scale, bool unsigned_flag) { - return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1)); + /* Precision can't be negative thus ignore unsigned_flag when length is 0. */ + DBUG_ASSERT(length || !scale); + return (uint) (length - (scale>0 ? 1:0) - + (unsigned_flag || !length ? 0:1)); } inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag) { + /* + When precision is 0 it means that original length was also 0. Thus + unsigned_flag is ignored in this case. + */ + DBUG_ASSERT(precision || !scale); set_if_smaller(precision, DECIMAL_MAX_PRECISION); - return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1)); + return (uint32)(precision + (scale>0 ? 1:0) + + (unsigned_flag || !precision ? 0:1)); } inline -- cgit v1.2.1 From 1a68ec2809726e12f148a07cf3771c3d73d9983e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 May 2008 13:49:26 +0300 Subject: Fix for bug #35298: GROUP_CONCAT with DISTINCT can crash the server The bug is a regression introduced by the patch for bug32798. The code in Item_func_group_concat::clear() relied on the 'distinct' variable to check if 'unique_filter' was initialized. That, however, is not always valid because Item_func_group_concat::setup() can do shortcuts in some cases w/o initializing 'unique_filter'. Fixed by checking the value of 'unique_filter' instead of 'distinct' before dereferencing. mysql-test/r/func_gconcat.result: Added test cases for bugs #35298 and #36024. mysql-test/t/func_gconcat.test: Added test cases for bugs #35298 and #36024. sql/item_sum.cc: Check if unique_filter != NULL before dereferencing it. Non-zero value of distinct does not always mean that unique_filter is initialized because Item_func_group_concat::setup() can do shortcuts is some cases --- sql/item_sum.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 91f9889b03f..91320d6b56b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3222,7 +3222,7 @@ void Item_func_group_concat::clear() no_appended= TRUE; if (tree) reset_tree(tree); - if (distinct) + if (unique_filter) unique_filter->reset(); /* No need to reset the table as we never call write_row */ } -- cgit v1.2.1 From 5a1b7ddb683a34c0a512c890a11170e0b0b14da2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 May 2008 21:43:46 +0500 Subject: Partial rollback of fix for bug #30059: End-space truncation is inconsistent or incorrect. For better conformance with standard, truncation procedure of CHAR columns has been changed to ignore truncation of trailing whitespace characters (note has been removed). Finally, for columns with non-binary charsets: 1. CHAR(N) columns silently ignore trailing whitespace truncation; 2. VARCHAR and TEXT columns issue Note about truncation. BLOBs and other columns with BINARY charset are unaffected. mysql-test/r/bdb.result: Rollback of bug #30059 fix. mysql-test/r/heap.result: Rollback of bug #30059 fix. mysql-test/r/innodb.result: Rollback of bug #30059 fix. mysql-test/r/myisam.result: Rollback of bug #30059 fix. mysql-test/r/strict.result: Rollback of bug #30059 fix. mysql-test/r/type_binary.result: Rollback of bug #30059 fix. mysql-test/r/warnings.result: Updated test case for bug #30059. sql/field.cc: Post-commit fix for bug #30059. The Field_longstr::report_if_important_data method has been changed to notify about trailing spaces only if the new count_spaces parameter is TRUE. The Field_string::store method has been changed to ignore trailing whitespace truncation (CHAR column type). sql/field.h: Post-commit fix for bug #30059. The Field_longstr::report_if_important_data method declaration has been changed to accept extra parameter: bool count_spaces. --- sql/field.cc | 18 ++++++++++++------ sql/field.h | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 18bb7153060..d840034f8dc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5868,6 +5868,7 @@ check_string_copy_error(Field_str *field, Field_longstr::report_if_important_data() ptr - Truncated rest of string end - End of truncated string + count_spaces - Treat traling spaces as important data RETURN VALUES 0 - None was truncated (or we don't count cut fields) @@ -5877,10 +5878,12 @@ check_string_copy_error(Field_str *field, Check if we lost any important data (anything in a binary string, or any non-space in others). If only trailing spaces was lost, send a truncation note, otherwise send a truncation error. + Silently ignore traling spaces if the count_space parameter is FALSE. */ int -Field_longstr::report_if_important_data(const char *ptr, const char *end) +Field_longstr::report_if_important_data(const char *ptr, const char *end, + bool count_spaces) { if ((ptr < end) && table->in_use->count_cuted_fields) { @@ -5890,10 +5893,13 @@ Field_longstr::report_if_important_data(const char *ptr, const char *end) set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); else set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + return 2; } - else /* If we lost only spaces then produce a NOTE, not a WARNING */ + else if (count_spaces) + { /* If we lost only spaces then produce a NOTE, not a WARNING */ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); - return 2; + return 2; + } } return 0; } @@ -5929,7 +5935,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - return report_if_important_data(from_end_pos, from + length); + return report_if_important_data(from_end_pos, from + length, FALSE); } @@ -6388,7 +6394,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - return report_if_important_data(from_end_pos, from + length); + return report_if_important_data(from_end_pos, from + length, TRUE); } @@ -7025,7 +7031,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - return report_if_important_data(from_end_pos, from + length); + return report_if_important_data(from_end_pos, from + length, TRUE); oom_error: /* Fatal OOM error */ diff --git a/sql/field.h b/sql/field.h index c82d65147ac..8d771a151a7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -455,7 +455,8 @@ public: class Field_longstr :public Field_str { protected: - int report_if_important_data(const char *ptr, const char *end); + int report_if_important_data(const char *ptr, const char *end, + bool count_spaces); public: Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, -- cgit v1.2.1 From a6f7fa35b1e7c97b16c27673aeb2846d23c2a342 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 May 2008 09:41:22 +0200 Subject: Bug#32575 - Parse error of stmt with extended comments on slave side Problem was that mysql_create_view did not remove all comments characters when writing to binlog, resulting in parse error of stmt on slave side. Solution was to use the recreated select clause and add a generated CHECK OPTION clause if needed. mysql-test/r/rpl_sp.result: Bug#32575 - Parse error of stmt with extended comments on slave side Updated test result mysql-test/r/rpl_view.result: Bug#32575 - Parse error of stmt with extended comments on slave side Updated test result mysql-test/t/rpl_view.test: Bug#32575 - Parse error of stmt with extended comments on slave side Added test case sql/sql_view.cc: Bug#32575 - Parse error of stmt with extended comments on slave side Problem was that mysql_create_view did not remove all comments characters when writing to binlog, resulting in parse error of stmt on slave side. Solution was to use the recreated select clause and generate 'WITH {LOCAL|CASCADED} CHECK OPTION'. --- sql/sql_view.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4c8e6e80c41..de92d6dc3b9 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -649,7 +649,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, buff.append(')'); } buff.append(STRING_WITH_LEN(" AS ")); - buff.append(views->source.str, views->source.length); + buff.append(views->query.str, views->query.length); + if (views->with_check == VIEW_CHECK_LOCAL) + buff.append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION")); + else if (views->with_check == VIEW_CHECK_CASCADED) + buff.append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION")); Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); mysql_bin_log.write(&qinfo); @@ -926,8 +930,6 @@ loop_out: } DBUG_RETURN(0); err: - view->query.str= NULL; - view->query.length= 0; view->md5.str= NULL; view->md5.length= 0; DBUG_RETURN(error); -- cgit v1.2.1 From e7e49eb69ee6ca949d8f885505da572bb1d394c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 May 2008 21:01:13 +0500 Subject: Fixed bug #36055: mysql_upgrade doesn't really 'upgrade' tables The REPAIR TABLE ... USE_FRM query silently corrupts data of tables with old .FRM file version. The mysql_upgrade client program or the REPAIR TABLE query (without the USE_FRM clause) can't prevent this trouble, because in the common case they don't upgrade .FRM file to compatible structure. 1. Evaluation of the REPAIR TABLE ... USE_FRM query has been modified to reject such tables with the message: "Failed repairing incompatible .FRM file". 2. REPAIR TABLE query (without USE_FRM clause) evaluation has been modified to upgrade .FRM files to current version. 3. CHECK TABLE ... FOR UPGRADE query evaluation has been modified to return error status when .FRM file has incompatible version. 4. mysql_upgrade and mysqlcheck client programs call CHECK TABLE FOR UPGRADE and REPAIR TABLE queries, so their behaviors have been changed too to upgrade .FRM files with incompatible version numbers. mysql-test/std_data/bug36055.MYD: Added test data for bug #36055. mysql-test/std_data/bug36055.MYI: Added test data for bug #36055. mysql-test/std_data/bug36055.frm: Added test data for bug #36055. mysql-test/r/repair.result: Added test case for bug# 36055. mysql-test/t/repair.test: Added test case for bug# 36055. sql/handler.cc: Fixed bug #36055: mysql_upgrade doesn't really 'upgrade' tables The handler::ha_check_for_upgrade method has been modified to return error if .FRM file has incompatible version number. sql/sql_table.cc: Fixed bug #36055: mysql_upgrade doesn't really 'upgrade' tables The prepare_for_repair function has been modified to reject REPAIR TABLE ... USE_FRM queries on incompatible .FRM files with the message: "Failed repairing incompatible .FRM file". --- sql/handler.cc | 2 ++ sql/sql_table.cc | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index bfad10f986f..40b85a0901c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1980,6 +1980,8 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt) } } } + if (table->s->frm_version != FRM_VER_TRUE_VARCHAR) + return HA_ADMIN_NEEDS_ALTER; return check_for_upgrade(check_opt); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9e1a8151e3a..f1de63892d5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2118,6 +2118,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, const char **ext= table->file->bas_ext(); MY_STAT stat_info; + if (table->s->frm_version != FRM_VER_TRUE_VARCHAR) + { + error= send_check_errmsg(thd, table_list, "repair", + "Failed reparing incompatible .FRM file"); + goto end; + } + /* Check if this is a table type that stores index and data separately, like ISAM or MyISAM. We assume fixed order of engine file name -- cgit v1.2.1 From 66367aeea83a0cd7f583a0194651a235b63975a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2008 20:27:46 +0500 Subject: Fixed bug #36488: regexp returns false matches, concatenating with previous rows. The WHERE clause containing expression: CONCAT(empty_field1, empty_field2, ..., 'literal constant', ...) REGEXP 'regular expression' may return wrong matches. Optimization of the CONCAT function has been fixed. mysql-test/r/func_concat.result: Added test case for bug #36488. mysql-test/t/func_concat.test: Added test case for bug #36488. sql/item_strfunc.cc: Fixed bug #36488. The Item_func_concat::val_str method is optimized to use first non-empty argument of the CONCAT function for in-place result accumulation. This optimization is acceptable if that first argument is not a constant. However, current implementation checks this condition only for the first actual argument of the CONCAT function. So, the Item_func_concat::val_str method can corrupt values of, for example, literal strings by appending random data. The Item_func_concat::val_str method has been modified to take into account the ability to be modified in-place for the first non-empty argument. --- sql/item_strfunc.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sql') diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4e72f117869..c443364ce52 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -294,6 +294,12 @@ String *Item_func_concat::val_str(String *str) { if (!(res=args[i]->val_str(str))) goto null; + /* + CONCAT accumulates its result in the result of its the first + non-empty argument. Because of this we need is_const to be + evaluated only for it. + */ + is_const= args[i]->const_item() || !args[i]->used_tables(); } else { -- cgit v1.2.1 From 55012e427bc4b3b6a5ffa070e229c519c8cd0b98 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 May 2008 19:13:24 -0400 Subject: Bug#36570: Parse error of CREATE PROCEDURE stmt with comments on \ slave The stored-routine code took the contents of the (lowest) parser and copied it directly to the binlog, which causes problems if there is a special case of interpretation at the parser level -- which there is, in the "/*!VER */" comments. The trailing "*/" caused errors on the slave, naturally. Now, since by that point we have /properly/ created parse-tree (as the rest of the server should do!) for the stored-routine CREATE, we can construct a perfect statement from that information, instead of writing uncertain information from an unknown parser state. Fortunately, there's already a function nearby that does exactly that. --- Update for Bug#36570. Qualify routine names with db name when writing to the binlog ONLY if the source text is qualified. mysql-test/r/binlog_innodb.result: Offsets changed due to quoting. --- New offset to account for db-qualified names. mysql-test/r/ctype_cp932_binlog.result: Offsets changed due to quoting. --- Qualify routine names with DB. Offsets change also. mysql-test/r/mysqlbinlog.result: Case changed in result due to interpretation of data instead of literal recitation. --- Qualify procedure name with db. mysql-test/r/rpl_sp.result: Offsets changed due to quoting. Added tests. --- Qualify routine names with DB if qualified in query. Offsets change also. mysql-test/t/rpl_sp.test: Add version-limiting quotes to exercise bug#36570. Test that backtick-quoted identifiers and labels work also. --- Use different db to show qualification works. Qualify routine names with DB if qualified in query. sql/sp.cc: In create_string, we may not have a sp_name parameter yet, so instead pass the char* and length of the only member we'd get out of it. Having done that, we can use the same function to write the CREATE (FUNC|TRIG|PROC) statement to the binlog as we always used to display the statement to the user. --- Make the db name part of the CREATE string if it is specified. Specify it in part of writing to the binlog when creating a new routine. sql/sp_head.cc: Set the sp_head m_explicit_name member as the sp_name member is set. We can not peek at this later, as the sp_name is gone by then. sql/sp_head.h: Add a member to track whether the name is qualified with the database. --- sql/sp.cc | 62 ++++++++++++++++++++++++++++++++++++---------------------- sql/sp_head.cc | 4 ++++ sql/sp_head.h | 1 + 3 files changed, 44 insertions(+), 23 deletions(-) (limited to 'sql') diff --git a/sql/sp.cc b/sql/sp.cc index 7224d3c4f0e..2392cabb220 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -25,7 +25,8 @@ static bool create_string(THD *thd, String *buf, int sp_type, - sp_name *name, + const char *db, ulong dblen, + const char *name, ulong namelen, const char *params, ulong paramslen, const char *returns, ulong returnslen, const char *body, ulong bodylen, @@ -426,12 +427,13 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, */ if (!create_string(thd, &defstr, - type, - name, - params, strlen(params), - returns, strlen(returns), - body, strlen(body), - &chistics, &definer_user_name, &definer_host_name)) + type, + NULL, 0, + name->m_name.str, name->m_name.length, + params, strlen(params), + returns, strlen(returns), + body, strlen(body), + &chistics, &definer_user_name, &definer_host_name)) { ret= SP_INTERNAL_ERROR; goto end; @@ -518,6 +520,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) DBUG_ENTER("db_create_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length, sp->m_name.str)); + String retstr(64); if (!(table= open_proc_table_for_update(thd))) ret= SP_OPEN_TABLE_FAILED; @@ -568,7 +571,6 @@ db_create_routine(THD *thd, int type, sp_head *sp) store(sp->m_params.str, sp->m_params.length, system_charset_info); if (sp->m_type == TYPE_ENUM_FUNCTION) { - String retstr(64); sp_returns_type(thd, retstr, sp); table->field[MYSQL_PROC_FIELD_RETURNS]-> store(retstr.ptr(), retstr.length(), system_charset_info); @@ -625,13 +627,21 @@ db_create_routine(THD *thd, int type, sp_head *sp) String log_query; log_query.set_charset(system_charset_info); - log_query.append(STRING_WITH_LEN("CREATE ")); - append_definer(thd, &log_query, &thd->lex->definer->user, - &thd->lex->definer->host); - log_query.append(thd->lex->stmt_definition_begin, - (char *)sp->m_body_begin - - thd->lex->stmt_definition_begin + - sp->m_body.length); + + if (!create_string(thd, &log_query, + sp->m_type, + (sp->m_explicit_name ? sp->m_db.str : NULL), + (sp->m_explicit_name ? sp->m_db.length : 0), + sp->m_name.str, sp->m_name.length, + sp->m_params.str, sp->m_params.length, + retstr.c_ptr(), retstr.length(), + sp->m_body.str, sp->m_body.length, + sp->m_chistics, &(thd->lex->definer->user), + &(thd->lex->definer->host))) + { + ret= SP_INTERNAL_ERROR; + goto done; + } /* Such a statement can always go directly to binlog, no trans cache */ Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0, @@ -1797,17 +1807,18 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, */ static bool create_string(THD *thd, String *buf, - int type, - sp_name *name, - const char *params, ulong paramslen, - const char *returns, ulong returnslen, - const char *body, ulong bodylen, - st_sp_chistics *chistics, + int type, + const char *db, ulong dblen, + const char *name, ulong namelen, + const char *params, ulong paramslen, + const char *returns, ulong returnslen, + const char *body, ulong bodylen, + st_sp_chistics *chistics, const LEX_STRING *definer_user, const LEX_STRING *definer_host) { /* Make some room to begin with */ - if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen + + if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen + chistics->comment.length + 10 /* length of " DEFINER= "*/ + USER_HOST_BUFF_SIZE)) return FALSE; @@ -1818,7 +1829,12 @@ create_string(THD *thd, String *buf, buf->append(STRING_WITH_LEN("FUNCTION ")); else buf->append(STRING_WITH_LEN("PROCEDURE ")); - append_identifier(thd, buf, name->m_name.str, name->m_name.length); + if (dblen > 0) + { + append_identifier(thd, buf, db, dblen); + buf->append('.'); + } + append_identifier(thd, buf, name, namelen); buf->append('('); buf->append(params, paramslen); buf->append(')'); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 46f3d25c441..aea81e301ef 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -522,6 +522,8 @@ sp_head::init(LEX *lex) m_qname.str= NULL; m_qname.length= 0; + m_explicit_name= false; + m_db.str= NULL; m_db.length= 0; @@ -564,6 +566,8 @@ sp_head::init_sp_name(THD *thd, sp_name *spname) m_name.str= strmake_root(thd->mem_root, spname->m_name.str, spname->m_name.length); + m_explicit_name= spname->m_explicit_name; + if (spname->m_qname.length == 0) spname->init_qname(thd); diff --git a/sql/sp_head.h b/sql/sp_head.h index 0e710196603..11ff7160c03 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -121,6 +121,7 @@ public: st_sp_chistics *m_chistics; ulong m_sql_mode; // For SHOW CREATE and execution LEX_STRING m_qname; // db.name + bool m_explicit_name; /**< Prepend the db name? */ /** Key representing routine in the set of stored routines used by statement. [routine_type]db.name\0 -- cgit v1.2.1 From 0fb1527e9556940d30ab14b11742c03510db081d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 May 2008 17:05:55 +0300 Subject: Bug #36011: server crash with explain extended on query with dependent subqueries An IN subquery is executed on EXPLAIN when it's not correlated. If the subquery required a temporary table for its execution not all the internal structures were restored from pointing to the items of the temporary table to point back to the items of the subquery. Fixed by restoring the ref array when a temp tables were used in executing the IN subquery during EXPLAIN EXTENDED. mysql-test/r/subselect.result: Bug #36011: test case mysql-test/t/subselect.test: Bug #36011: test case sql/sql_select.cc: Bug #36011: restore the ref array after execution when there were temp tables. --- sql/sql_select.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 11062998e6a..d1e5837329b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2104,11 +2104,12 @@ JOIN::exec() /* With EXPLAIN EXTENDED we have to restore original ref_array for a derived table which is always materialized. - Otherwise we would not be able to print the query correctly. + We also need to do this when we have temp table(s). + Otherwise we would not be able to print the query correctly. */ - if (items0 && - (thd->lex->describe & DESCRIBE_EXTENDED) && - select_lex->linkage == DERIVED_TABLE_TYPE) + if (items0 && (thd->lex->describe & DESCRIBE_EXTENDED) && + (select_lex->linkage == DERIVED_TABLE_TYPE || + exec_tmp_table1 || exec_tmp_table2)) set_items_ref_array(items0); DBUG_VOID_RETURN; -- cgit v1.2.1 From f197f3abb40c8af4687e7535e9dc53bf4621b939 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 17 May 2008 12:53:47 +0500 Subject: Bug #36705 key_buffer_size of >= 2G allocates all availabel virtual memory on 64-bit wondo. temporary variables of 'long' types were used to store ulong values, that causes init_key_cache to receive distorted parameters sql/handler.cc: Bug #36705 key_buffer_size of >= 2G allocates all availabel virtual memory on 64-bit wondo. types of temporary variables changed to match init_key_cache() parameters --- sql/handler.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index 40b85a0901c..0de772e366b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2350,8 +2350,8 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) if (!key_cache->key_cache_inited) { pthread_mutex_lock(&LOCK_global_system_variables); - long tmp_buff_size= (long) key_cache->param_buff_size; - long tmp_block_size= (long) key_cache->param_block_size; + ulong tmp_buff_size= (ulong) key_cache->param_buff_size; + uint tmp_block_size= (uint) key_cache->param_block_size; uint division_limit= key_cache->param_division_limit; uint age_threshold= key_cache->param_age_threshold; pthread_mutex_unlock(&LOCK_global_system_variables); -- cgit v1.2.1 From 29e7fa258d7a20bb2bd5305c2e0fe6ae3b1c76af Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 May 2008 14:21:25 +0500 Subject: Fixed bug#36676: multiupdate using LEFT JOIN updates only first row or fails with an error: ERROR 1022 (23000): Can't write; duplicate key in table '' The server uses intermediate temporary table to store updated row data. The first column of this table contains rowid. Current server implementation doesn't reset NULL flag of that column even if the server fills a column with rowid. To keep each rowid unique, there is an unique index. An insertion into an unique index takes into account NULL flag of key value and ignores real data if NULL flag is set. So, insertion of actually different rowids may lead to two kind of problems. Visible effect of each of these problems depends on an initial engine type of temporary table: 1. If multiupdate initially creates temporary table as a MyISAM table (a table contains blob columns, and the create_tmp_table function assumes, that this table is large), it inserts only one single row and updates only rows with one corresponding rowid. Other rows are silently ignored. 2. If multiupdate initially creates MEMORY temporary table, fills it with data and reaches size limit for MEMORY tables (max_heap_table_size), multiupdate converts MEMORY table into MyISAM table and fails with an error: ERROR 1022 (23000): Can't write; duplicate key in table '' Multiupdate has been fixed to update the NULL flag of temporary table rowid columns. mysql-test/r/multi_update_tiny_hash.result: Added test case for bug#36676. mysql-test/t/multi_update_tiny_hash-master.opt: Added test case for bug#36676. mysql-test/t/multi_update_tiny_hash.test: Added test case for bug#36676. sql/sql_update.cc: Fixed bug#36676: multiupdate using LEFT JOIN updates only first row or fails with an error: ERROR 1022 (23000): Can't write; duplicate key in table '' The multi_update::send_data method has been modified to reset null bits of fields containing rowids. --- sql/sql_update.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sql') diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a8238141f25..6830564111b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1440,6 +1440,12 @@ bool multi_update::send_data(List ¬_used_values) tbl->file->position(tbl->record[0]); memcpy((char*) tmp_table->field[field_num]->ptr, (char*) tbl->file->ref, tbl->file->ref_length); + /* + For outer joins a rowid field may have no NOT_NULL_FLAG, + so we have to reset NULL bit for this field. + (set_notnull() resets NULL bit only if available). + */ + tmp_table->field[field_num]->set_notnull(); field_num++; } while ((tbl= tbl_it++)); -- cgit v1.2.1 From c9232b936d5695c64e23dab18c0cabae767d5cb9 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 28 May 2008 15:03:47 +0500 Subject: Updating charset doc files. Thanks to Paul for preparing the up-to-date files reflecting 4.1 changes. --- sql/share/charsets/README | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'sql') diff --git a/sql/share/charsets/README b/sql/share/charsets/README index 172d1ee8e1e..3c5b3206faa 100644 --- a/sql/share/charsets/README +++ b/sql/share/charsets/README @@ -1,28 +1,31 @@ -This directory holds configuration files which allow MySQL to work with +This directory holds configuration files that enable MySQL to work with different character sets. It contains: -*.conf - Each conf file contains four tables which describe character types, +charset_name.xml + Each charset_name.xml file contains information for a simple character + set. The information in the file describes character types, lower- and upper-case equivalencies and sorting orders for the character values in the set. -Index - The Index file lists all of the available charset configurations. +Index.xml + The Index.xml file lists all of the available charset configurations, + including collations. - Each charset is paired with a number. The number is stored - IN THE DATABASE TABLE FILES and must not be changed. Always - add new character sets to the end of the list, so that the - numbers of the other character sets will not be changed. + Each collation must have a unique number. The number is stored + IN THE DATABASE TABLE FILES and must not be changed. + + The max-id attribute of the element must be set to + the largest collation number. Compiled in or configuration file? When should a character set be compiled in to MySQL's string library - (libmystrings), and when should it be placed in a configuration - file? + (libmystrings), and when should it be placed in a charset_name.xml + configuration file? If the character set requires the strcoll functions or is a multi-byte character set, it MUST be compiled in to the string library. If it does not require these functions, it should be - placed in a configuration file. + placed in a charset_name.xml configuration file. If the character set uses any one of the strcoll functions, it must define all of them. Likewise, if the set uses one of the @@ -30,11 +33,7 @@ Compiled in or configuration file? more information on how to add a complex character set to MySQL. Syntax of configuration files - The syntax is very simple. Comments start with a '#' character and - proceed to the end of the line. Words are separated by arbitrary - amounts of whitespace. - - For the character set configuration files, every word must be a - number in hexadecimal format. The ctype array takes up the first - 257 words; the to_lower, to_upper and sort_order arrays take up 256 - words each after that. + The syntax is very simple. Words in array elements are + separated by arbitrary amounts of whitespace. Each word must be a + number in hexadecimal format. The ctype array has 257 words; the + other arrays (lower, upper, etc.) take up 256 words each after that. -- cgit v1.2.1 From da4cfa6d1ec4e02247a41fe3af068ffd042e23be Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 3 Jun 2008 13:12:37 +0300 Subject: Bug#37069 (5.0): implement --skip-federated mysql-test/r/federated_disabled.result: Bug#37069 (5.0): test case mysql-test/t/federated_disabled-master.opt: Bug#37069 (5.0): test case mysql-test/t/federated_disabled.test: Bug#37069 (5.0): test case --- sql/mysqld.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c239530f2fc..cdae94f0a61 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -328,7 +328,7 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; -static my_bool opt_bdb, opt_isam, opt_ndbcluster, opt_merge; +static my_bool opt_bdb, opt_isam, opt_ndbcluster, opt_merge, opt_federated; static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; @@ -4989,7 +4989,8 @@ enum options_mysqld OPT_INNODB_ROLLBACK_ON_TIMEOUT, OPT_SECURE_FILE_PRIV, OPT_KEEP_FILES_ON_CREATE, - OPT_INNODB_ADAPTIVE_HASH_INDEX + OPT_INNODB_ADAPTIVE_HASH_INDEX, + OPT_FEDERATED }; @@ -5175,6 +5176,9 @@ Disable with --skip-external-locking.", 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"federated", OPT_FEDERATED, "Enable Federated storage engine. Disable with \ +--skip-federated.", + (gptr*) &opt_federated, (gptr*) &opt_federated, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, /* We must always support the next option to make scripts like mysqltest easier to do */ {"gdb", OPT_DEBUGGING, @@ -7322,6 +7326,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), else have_merge_db= SHOW_OPTION_DISABLED; break; +#ifdef HAVE_FEDERATED_DB + case OPT_FEDERATED: + if (opt_federated) + have_federated_db= SHOW_OPTION_YES; + else + have_federated_db= SHOW_OPTION_DISABLED; + break; +#endif #ifdef HAVE_BERKELEY_DB case OPT_BDB_NOSYNC: /* Deprecated option */ -- cgit v1.2.1