diff options
author | unknown <pem@mysql.com> | 2003-12-19 18:03:27 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2003-12-19 18:03:27 +0100 |
commit | 4cd90227696cdc8dced6efec7aad9836bf93dd7c (patch) | |
tree | 00894c28662192eed25fdacc555298265a2880ac /sql | |
parent | 58a52a2a84eafe535317a533af56a81d81a8fd56 (diff) | |
parent | bfe77e3398944bed4c919ba0c7477a4318d9f2cc (diff) | |
download | mariadb-git-4cd90227696cdc8dced6efec7aad9836bf93dd7c.tar.gz |
Merge 4.1 to 5.0.
BitKeeper/etc/logging_ok:
auto-union
client/mysql.cc:
Auto merged
configure.in:
Auto merged
client/mysqltest.c:
Auto merged
include/my_global.h:
Auto merged
include/my_pthread.h:
Auto merged
include/mysql_com.h:
Auto merged
libmysql/libmysql.c:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
myisam/mi_check.c:
Auto merged
mysql-test/r/insert.result:
Auto merged
mysql-test/r/join_outer.result:
Auto merged
mysql-test/r/multi_update.result:
Auto merged
mysql-test/r/query_cache.result:
Auto merged
mysql-test/r/symlink.result:
Auto merged
mysql-test/t/func_time.test:
Auto merged
mysql-test/t/insert.test:
Auto merged
mysql-test/t/multi_update.test:
Auto merged
mysql-test/t/query_cache.test:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_func.h:
Auto merged
sql/item_subselect.cc:
Auto merged
sql/item_sum.cc:
Auto merged
sql/item_sum.h:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/lex.h:
Auto merged
sql/log.cc:
Auto merged
sql/log_event.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/records.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/slave.cc:
Auto merged
sql/sql_acl.h:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_rename.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.h:
Auto merged
sql/share/czech/errmsg.txt:
Auto merged
sql/share/romanian/errmsg.txt:
Auto merged
Diffstat (limited to 'sql')
68 files changed, 938 insertions, 624 deletions
diff --git a/sql/field.cc b/sql/field.cc index 237427a9d80..a9029b893e3 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -791,7 +791,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) if (zerofill) { left_wall=to-1; - while (pos != left_wall) // Fill with zeros + while (pos > left_wall) // Fill with zeros *pos--='0'; } else @@ -799,7 +799,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) left_wall=to+(sign_char != 0)-1; if (!expo_sign_char) // If exponent was specified, ignore prezeros { - for (;pos != left_wall && pre_zeros_from !=pre_zeros_end; + for (;pos > left_wall && pre_zeros_from !=pre_zeros_end; pre_zeros_from++) *pos--= '0'; } @@ -1016,7 +1016,7 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) return 0; if (*a_ptr == '-') return -1; - else if (*b_ptr == '-') + if (*b_ptr == '-') return 1; while (a_ptr != end) @@ -2853,34 +2853,72 @@ int Field_timestamp::store(double nr) function. */ -static longlong fix_datetime(longlong nr) +static longlong fix_datetime(longlong nr, TIME *time_res, + const char *field_name, bool *error) { - current_thd->last_cuted_field= 0; + long part1,part2; + + *error= 0; if (nr == LL(0) || nr >= LL(10000101000000)) - return nr; // Normal datetime >= Year 1000 + goto ok; if (nr < 101) goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) - return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) - return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } if (nr < 10000101L) goto err; if (nr <= 99991231L) - return nr*1000000L; + { + nr= nr*1000000L; + goto ok; + } if (nr < 101000000L) goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) - return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 - + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + if (time_res->year <= 9999 && time_res->month <= 12 && + time_res->day <= 31 && time_res->hour <= 23 && + time_res->minute <= 59 && time_res->second <= 59) + return nr; + err: - current_thd->last_cuted_field= 1; + THD *thd= current_thd; + if (thd->count_cuted_fields) + { + thd->cuted_fields++; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED), + field_name, thd->row_count); + } + *error= 1; return LL(0); } @@ -2888,24 +2926,17 @@ static longlong fix_datetime(longlong nr) int Field_timestamp::store(longlong nr) { TIME l_time; - time_t timestamp; - long part1,part2; + time_t timestamp= 0; + bool error; - if ((nr=fix_datetime(nr))) + if ((nr= fix_datetime(nr, &l_time, field_name, &error))) { long not_used; - part1=(long) (nr/LL(1000000)); - part2=(long) (nr - (longlong) part1*LL(1000000)); - l_time.year= (int) (part1/10000L); part1%=10000L; - l_time.month= (int) part1 / 100; - l_time.day= (int) part1 % 100; - l_time.hour= (int) (part2/10000L); part2%=10000L; - l_time.minute=(int) part2 / 100; - l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time, ¬_used); - } - else - timestamp=0; + + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) + goto err; + timestamp= my_gmt_sec(&l_time, ¬_used); + } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -2914,9 +2945,12 @@ int Field_timestamp::store(longlong nr) else #endif longstore(ptr,(uint32) timestamp); - if (current_thd->last_cuted_field) - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - return 0; + return error; + +err: + longstore(ptr,(uint32) 0); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + return 1; } @@ -3350,7 +3384,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); return 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) + if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); if (nr != 0 || len != 4) { @@ -3363,6 +3397,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) return 0; } + int Field_year::store(double nr) { if (nr < 0.0 || nr >= 2155.0) @@ -3825,15 +3860,10 @@ int Field_datetime::store(double nr) int Field_datetime::store(longlong nr) { - int error= 0; - if (nr < 0 || nr > LL(99991231235959)) - { - nr=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - error= 1; - } - else - nr=fix_datetime(nr); + TIME not_used; + bool error; + + nr= fix_datetime(nr, ¬_used, field_name, &error); #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -3842,11 +3872,10 @@ int Field_datetime::store(longlong nr) else #endif longlongstore(ptr,nr); - if (current_thd->last_cuted_field) - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); return error; } + void Field_datetime::store_time(TIME *ltime,timestamp_type type) { longlong tmp; @@ -5064,7 +5093,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) uint tmp=find_type(typelib, from, length, 0); if (!tmp) { - if (length < 6) // Can't be more than 99999 enums + if (length < 6) // Can't be more than 99999 enums { /* This is for reading numbers with LOAD DATA INFILE */ char *end; @@ -5159,7 +5188,7 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)), { uint tmp=(uint) Field_enum::val_int(); if (!tmp || tmp > typelib->count) - val_ptr->length(0); + val_ptr->set("", 0, field_charset); else val_ptr->set((const char*) typelib->type_names[tmp-1], (uint) strlen(typelib->type_names[tmp-1]), @@ -5224,12 +5253,13 @@ void Field_enum::sql_type(String &res) const int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) { - bool set_warning= 0; + bool got_warning= 0; int err= 0; char *not_used; uint not_used2; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ if (use_conversion(cs, field_charset)) { @@ -5238,7 +5268,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) length= tmpstr.length(); } ulonglong tmp= find_set(typelib, from, length, ¬_used, ¬_used2, - &set_warning); + &got_warning); if (!tmp && length && length < 22) { /* This is for reading numbers with LOAD DATA INFILE */ @@ -5248,16 +5278,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1)) { tmp=0; - THD *thd= current_thd; - if (thd->count_cuted_fields) - { - thd->cuted_fields++; - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED), - field_name, 0); - } + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); } } + else if (got_warning) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); store_type(tmp); return err; } diff --git a/sql/field.h b/sql/field.h index 508fbad41a1..e3b4bf29fb8 100644 --- a/sql/field.h +++ b/sql/field.h @@ -872,11 +872,14 @@ public: enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg, cs) {}; - Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + unireg_check_arg, field_name_arg, table_arg, cs) + {} + Field_varstring(uint32 len_arg,bool maybe_null_arg, + const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg, cs) {}; + NONE, field_name_arg, table_arg, cs) + {} enum_field_types type() const { return FIELD_TYPE_VAR_STRING; } enum ha_base_keytype key_type() const @@ -924,9 +927,9 @@ public: :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, table_arg, cs), geom_flag(true), packlength(4) - { - flags|= BLOB_FLAG; - } + { + flags|= BLOB_FLAG; + } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index cbbb0d96d22..7796c063424 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -33,11 +33,9 @@ InnoDB */ #include "mysql_priv.h" #include "slave.h" -#include "sql_cache.h" #ifdef HAVE_INNOBASE_DB #include <m_ctype.h> -#include <assert.h> #include <hash.h> #include <myisampack.h> @@ -1860,7 +1858,7 @@ ha_innobase::store_key_val_for_row( || mysql_type == FIELD_TYPE_BLOB || mysql_type == FIELD_TYPE_LONG_BLOB) { - ut_a(key_part->key_part_flag & HA_PART_KEY); + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); if (is_null) { buff += key_part->length + 2; @@ -3345,7 +3343,7 @@ create_index( for (i = 0; i < n_fields; i++) { key_part = key->key_part + i; - /* (The flag HA_PART_KEY denotes in MySQL a column prefix + /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix field in an index: we only store a specified number of first bytes of the column to the index field.) The flag does not seem to be properly set by MySQL. Let us fall back on testing diff --git a/sql/item.cc b/sql/item.cc index e4023afe8a7..9ac4fbd6840 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -102,6 +102,14 @@ void Item::print_item_w_name(String *str) } +Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, + const char *field_name_par) + :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par), + depended_from(0) +{ + name = (char*) field_name_par; +} + // Constructor used by Item_field & Item_ref (see Item comment) Item_ident::Item_ident(THD *thd, Item_ident &item): Item(thd, item), @@ -676,10 +684,10 @@ String *Item_param::val_str(String* str) { switch (item_result_type) { case INT_RESULT: - str->set(int_value, default_charset()); + str->set(int_value, &my_charset_bin); return str; case REAL_RESULT: - str->set(real_value, 2, default_charset()); + str->set(real_value, 2, &my_charset_bin); return str; default: return (String*) &str_value; @@ -1764,12 +1772,11 @@ Item_result item_cmp_type(Item_result a,Item_result b) { if (a == STRING_RESULT && b == STRING_RESULT) return STRING_RESULT; - else if (a == INT_RESULT && b == INT_RESULT) + if (a == INT_RESULT && b == INT_RESULT) return INT_RESULT; else if (a == ROW_RESULT || b == ROW_RESULT) return ROW_RESULT; - else - return REAL_RESULT; + return REAL_RESULT; } diff --git a/sql/item.h b/sql/item.h index d8aea6552c3..4c6be932376 100644 --- a/sql/item.h +++ b/sql/item.h @@ -330,12 +330,8 @@ public: const char *field_name; st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, - const char *field_name_par) - :db_name(db_name_par), table_name(table_name_par), - field_name(field_name_par), depended_from(0) - { name = (char*) field_name_par; } - // Constructor used by Item_field & Item_ref (see Item comment) - Item_ident(THD *thd, Item_ident &item); + const char *field_name_par); + Item_ident::Item_ident(THD *thd, Item_ident &item); const char *full_name() const; bool remove_dependence_processor(byte * arg); diff --git a/sql/item_func.cc b/sql/item_func.cc index 01a5f1cdf3c..600258159e6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -320,6 +320,7 @@ void Item_func::print_op(String *str) str->append(')'); } + bool Item_func::eq(const Item *item, bool binary_cmp) const { /* Assume we don't have rtti */ @@ -375,8 +376,7 @@ String *Item_real_func::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -388,18 +388,17 @@ String *Item_num_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); } else { double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); } return str; } @@ -425,10 +424,10 @@ String *Item_int_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } @@ -454,18 +453,17 @@ String *Item_num_op::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); } else { double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); } return str; } @@ -1035,10 +1033,10 @@ String *Item_func_min_max::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } case REAL_RESULT: @@ -1046,8 +1044,7 @@ String *Item_func_min_max::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); return str; } case STRING_RESULT: @@ -1682,8 +1679,7 @@ String *Item_func_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); return str; } @@ -1703,10 +1699,10 @@ String *Item_func_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } diff --git a/sql/item_func.h b/sql/item_func.h index d3cfaf63b5a..c2aa62ec2d7 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -660,25 +660,31 @@ public: void fix_length_and_dec(); }; +/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ -class Item_func_bit_or :public Item_int_func +class Item_func_bit: public Item_int_func { public: - Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit(Item *a, Item *b) :Item_int_func(a, b) {} + Item_func_bit(Item *a) :Item_int_func(a) {} + void fix_length_and_dec() { unsigned_flag= 1; } + void print(String *str) { print_op(str); } +}; + +class Item_func_bit_or :public Item_func_bit +{ +public: + Item_func_bit_or(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "|"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; -class Item_func_bit_and :public Item_int_func +class Item_func_bit_and :public Item_func_bit { public: - Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_and(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "&"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; class Item_func_bit_count :public Item_int_func @@ -690,34 +696,32 @@ public: void fix_length_and_dec() { max_length=2; } }; -class Item_func_shift_left :public Item_int_func +class Item_func_shift_left :public Item_func_bit { public: - Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_left(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "<<"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; -class Item_func_shift_right :public Item_int_func +class Item_func_shift_right :public Item_func_bit { public: - Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_right(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return ">>"; } - void print(String *str) { print_op(str); } }; -class Item_func_bit_neg :public Item_int_func +class Item_func_bit_neg :public Item_func_bit { public: - Item_func_bit_neg(Item *a) :Item_int_func(a) {} + Item_func_bit_neg(Item *a) :Item_func_bit(a) {} longlong val_int(); const char *func_name() const { return "~"; } - void fix_length_and_dec() { unsigned_flag=1; } + void print(String *str) { Item_func::print(str); } }; + class Item_func_set_last_insert_id :public Item_int_func { public: @@ -1024,14 +1028,12 @@ public: }; -class Item_func_bit_xor : public Item_int_func +class Item_func_bit_xor : public Item_func_bit { public: - Item_func_bit_xor(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_xor(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "^"; } - void fix_length_xor_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; class Item_func_is_free_lock :public Item_int_func diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f40d38dd4a8..3cb03d7ea49 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1582,6 +1582,11 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org) } +/* + TODO: This needs to be fixed for multi-byte character set where numbers + are stored in more than one byte +*/ + String *Item_func_format::val_str(String *str) { double nr =args[0]->val(); @@ -1590,7 +1595,8 @@ String *Item_func_format::val_str(String *str) if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ dec= decimals ? decimals+1 : 0; - str->set(nr,decimals,default_charset()); + /* Here default_charset() is right as this is not an automatic conversion */ + str->set(nr,decimals, default_charset()); #ifdef HAVE_ISNAN if (isnan(nr)) return str; @@ -1839,14 +1845,11 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value, str->length(length); return str; } - else - { - if (tmp_value->alloc(length)) - return 0; - (void) tmp_value->copy(*res); - tmp_value->length(length); - return tmp_value; - } + if (tmp_value->alloc(length)) + return 0; + (void) tmp_value->copy(*res); + tmp_value->length(length); + return tmp_value; } res->length(length); return res; @@ -1947,7 +1950,7 @@ String *Item_func_rpad::val_str(String *str) int32 count= (int32) args[1]->val_int(); int32 byte_count= count * collation.collation->mbmaxlen; String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(str); + String *rpad = args[2]->val_str(&rpad_str); if (!res || args[1]->null_value || !rpad || count < 0) goto err; @@ -2384,6 +2387,10 @@ String* Item_func_export_set::val_str(String* str) null_value=1; return 0; } + /* + Arg count can only be 3, 4 or 5 here. This is guaranteed from the + grammar for EXPORT_SET() + */ switch(arg_count) { case 5: num_set_values = (uint) args[4]->val_int(); @@ -2513,7 +2520,7 @@ String *Item_func_quote::val_str(String *str) new_length= arg_length+2; /* for beginning and ending ' signs */ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) - new_length+= get_esc_bit(escmask, *from); + new_length+= get_esc_bit(escmask, (uchar) *from); /* We have to use realloc() instead of alloc() as we want to keep the diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a7949511f02..40b00cdd488 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -474,7 +474,7 @@ public: class Item_func_rpad :public Item_str_func { - String tmp_value; + String tmp_value, rpad_str; public: Item_func_rpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} @@ -486,7 +486,7 @@ public: class Item_func_lpad :public Item_str_func { - String tmp_value; + String tmp_value, lpad_str; public: Item_func_lpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6f5e2e492e7..43775e1c96c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -344,7 +344,7 @@ void Item_singlerow_subselect::bring_value() exec(); } -double Item_singlerow_subselect::val () +double Item_singlerow_subselect::val() { if (!exec() && !value->null_value) { @@ -358,7 +358,7 @@ double Item_singlerow_subselect::val () } } -longlong Item_singlerow_subselect::val_int () +longlong Item_singlerow_subselect::val_int() { if (!exec() && !value->null_value) { @@ -466,7 +466,7 @@ void Item_exists_subselect::fix_length_and_dec() max_columns= engine->cols(); } -double Item_exists_subselect::val () +double Item_exists_subselect::val() { if (exec()) { @@ -476,7 +476,7 @@ double Item_exists_subselect::val () return (double) value; } -longlong Item_exists_subselect::val_int () +longlong Item_exists_subselect::val_int() { if (exec()) { @@ -493,11 +493,11 @@ String *Item_exists_subselect::val_str(String *str) reset(); return 0; } - str->set(value,default_charset()); + str->set(value,&my_charset_bin); return str; } -double Item_in_subselect::val () +double Item_in_subselect::val() { if (exec()) { @@ -510,7 +510,7 @@ double Item_in_subselect::val () return (double) value; } -longlong Item_in_subselect::val_int () +longlong Item_in_subselect::val_int() { if (exec()) { @@ -536,7 +536,7 @@ String *Item_in_subselect::val_str(String *str) null_value= 1; return 0; } - str->set(value,default_charset()); + str->set(value, &my_charset_bin); return str; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f1ecced250d..3bc52159a96 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -140,7 +140,7 @@ Item_sum_num::val_str(String *str) double nr=val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -148,10 +148,13 @@ Item_sum_num::val_str(String *str) String * Item_sum_int::val_str(String *str) { - longlong nr=val_int(); + longlong nr= val_int(); if (null_value) return 0; - str->set(nr,default_charset()); + if (unsigned_flag) + str->set((ulonglong) nr, &my_charset_bin); + else + str->set(nr, &my_charset_bin); return str; } @@ -590,13 +593,13 @@ Item_sum_hybrid::val_str(String *str) case STRING_RESULT: return &value; case REAL_RESULT: - str->set(sum,decimals,default_charset()); + str->set(sum,decimals, &my_charset_bin); break; case INT_RESULT: if (unsigned_flag) - str->set((ulonglong) sum_int,default_charset()); + str->set((ulonglong) sum_int, &my_charset_bin); else - str->set((longlong) sum_int,default_charset()); + str->set((longlong) sum_int, &my_charset_bin); break; case ROW_RESULT: default: @@ -892,9 +895,16 @@ void Item_sum_avg::reset_field() void Item_sum_bit::reset_field() { + reset(); + int8store(result_field->ptr, bits); +} + +void Item_sum_bit::update_field() +{ char *res=result_field->ptr; - ulonglong nr=(ulonglong) args[0]->val_int(); - int8store(res,nr); + bits= uint8korr(res); + add(); + int8store(res, bits); } /* @@ -1032,37 +1042,6 @@ Item_sum_hybrid::min_max_update_int_field() } -void Item_sum_or::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr|= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - -void Item_sum_xor::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr^= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - -void Item_sum_and::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr&= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - Item_avg_field::Item_avg_field(Item_sum_avg *item) { name=item->name; @@ -1072,6 +1051,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item) maybe_null=1; } + double Item_avg_field::val() { double nr; @@ -1094,7 +1074,7 @@ String *Item_avg_field::val_str(String *str) double nr=Item_avg_field::val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1142,7 +1122,7 @@ String *Item_variance_field::val_str(String *str) double nr=val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1526,8 +1506,7 @@ String *Item_sum_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1552,8 +1531,7 @@ String *Item_sum_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else - str->set(nr,default_charset()); + str->set(nr, &my_charset_bin); return str; } diff --git a/sql/item_sum.h b/sql/item_sum.h index a80b6797068..afed152bb0e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -65,7 +65,18 @@ public: inline bool reset() { clear(); return add(); }; virtual void clear()= 0; virtual bool add()=0; + /* + Called when new group is started and results are being saved in + a temporary table. Similar to reset(), but must also store value in + result_field. Like reset() it is supposed to reset start value to + default. + */ virtual void reset_field()=0; + /* + Called for each new value in the group, when temporary table is in use. + Similar to add(), but uses temporary table field to obtain current value, + Updated value is then saved in the field. + */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } @@ -478,10 +489,10 @@ public: class Item_sum_bit :public Item_sum_int { - protected: +protected: ulonglong reset_bits,bits; - public: +public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} Item_sum_bit(THD *thd, Item_sum_bit &item): @@ -490,6 +501,7 @@ class Item_sum_bit :public Item_sum_int void clear(); longlong val_int(); void reset_field(); + void update_field(); void fix_length_and_dec() { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -497,11 +509,10 @@ class Item_sum_bit :public Item_sum_int class Item_sum_or :public Item_sum_bit { - public: +public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_or"; } Item *copy_or_same(THD* thd); }; @@ -510,10 +521,9 @@ class Item_sum_or :public Item_sum_bit class Item_sum_and :public Item_sum_bit { public: - Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} + Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_and"; } Item *copy_or_same(THD* thd); }; @@ -524,7 +534,6 @@ class Item_sum_xor :public Item_sum_bit Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_xor"; } Item *copy_or_same(THD* thd); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 7936006acc4..ae9d2be80f6 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -526,8 +526,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, 0, (*ptr) == 'U', &year), - intbuff, 10) - intbuff; + length= int10_to_str(calc_week(l_time, + (*ptr) == 'U' ? + WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST, + &year), + intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -537,8 +540,12 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, 1, (*ptr) == 'V', &year), - intbuff, 10) - intbuff; + length= int10_to_str(calc_week(l_time, + ((*ptr) == 'V' ? + (WEEK_YEAR | WEEK_FIRST_WEEKDAY) : + (WEEK_YEAR | WEEK_MONDAY_FIRST)), + &year), + intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -548,7 +555,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - (void) calc_week(l_time, 1, (*ptr) == 'X', &year); + (void) calc_week(l_time, + ((*ptr) == 'X' ? + WEEK_YEAR | WEEK_FIRST_WEEKDAY : + WEEK_YEAR | WEEK_MONDAY_FIRST), + &year); length= int10_to_str(year, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 4, '0'); } @@ -718,27 +729,51 @@ longlong Item_func_second::val_int() } -/* - Returns the week of year. +uint week_mode(uint mode) +{ + uint week_format= (mode & 7); + if (!(week_format & WEEK_MONDAY_FIRST)) + week_format^= WEEK_FIRST_WEEKDAY; + return week_format; +} - The bits in week_format has the following meaning: - 0 If not set: USA format: Sunday is first day of week - If set: ISO format: Monday is first day of week - 1 If not set: Week is in range 0-53 - If set Week is in range 1-53. +/* + The bits in week_format(for calc_week() function) has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. */ longlong Item_func_week::val_int() { uint year; - uint week_format; TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week_format= (uint) args[1]->val_int(); - return (longlong) calc_week(<ime, - (week_format & 2) != 0, - (week_format & 1) == 0, + return (longlong) calc_week(<ime, + week_mode((uint) args[1]->val_int()), &year); } @@ -749,7 +784,9 @@ longlong Item_func_yearweek::val_int() TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week=calc_week(<ime, 1, (args[1]->val_int() & 1) == 0, &year); + week= calc_week(<ime, + (week_mode((uint) args[1]->val_int()) | WEEK_YEAR), + &year); return week+year*100; } diff --git a/sql/log.cc b/sql/log.cc index 95ee4928971..59bc7c7fae2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -964,7 +964,7 @@ void MYSQL_LOG::new_file(bool need_lock) We log the whole file name for log file as the user may decide to change base names at some point. */ - THD* thd = current_thd; + THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */ Rotate_log_event r(thd,new_name+dirname_length(new_name)); r.set_log_pos(this); r.write(&log_file); @@ -1231,8 +1231,6 @@ bool MYSQL_LOG::write(Log_event* event_info) Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } @@ -1240,8 +1238,6 @@ bool MYSQL_LOG::write(Log_event* event_info) { Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 8c93a22cf6e..ca1b296009d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -239,6 +239,13 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) } +/* + This minimal constructor is for when you are not even sure that there is a + valid THD. For example in the server when we are shutting down or flushing + logs after receiving a SIGHUP (then we must write a Rotate to the binlog but + we have no THD, so we need this minimal constructor). +*/ + Log_event::Log_event() :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0), thd(0) @@ -1032,7 +1039,7 @@ Default database: '%s'", thd->variables.convert_set = 0; #endif close_thread_tables(thd); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); } #endif @@ -1794,10 +1801,10 @@ Slave: load data infile on table '%s' at log position %s in log \ slave_print_error(rli,sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", err, (char*)table_name, print_slave_db_safe(db)); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); if (thd->is_fatal_error) { diff --git a/sql/log_event.h b/sql/log_event.h index 6cc8a7ca06d..d615c0e361b 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -698,7 +698,7 @@ public: #ifndef MYSQL_CLIENT Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(),val(val_arg),type(type_arg) + :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) {} #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); @@ -841,7 +841,7 @@ public: Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg, uint ident_len_arg = 0, ulonglong pos_arg = LOG_EVENT_OFFSET) - :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg), + :Log_event(), new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)), alloced(0) {} diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1343c5e1e18..51c944d52ad 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -283,6 +283,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define tmp_file_prefix "#sql" /* Prefix for tmp tables */ #define tmp_file_prefix_length 4 +/* Flags for calc_week() function. */ +#define WEEK_MONDAY_FIRST 1 +#define WEEK_YEAR 2 +#define WEEK_FIRST_WEEKDAY 4 + struct st_table; class THD; @@ -418,6 +423,7 @@ int mysql_execute_command(THD *thd); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); +bool check_dup(const char *db, const char *name, TABLE_LIST *tables); #ifndef EMBEDDED_LIBRARY bool check_stack_overrun(THD *thd,char *dummy); #else @@ -431,17 +437,11 @@ void kill_mysql(void); void close_connection(THD *thd, uint errcode, bool lock); bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); -#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool no_grant, bool no_errors); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors); bool check_global_access(THD *thd, ulong want_access); -#else -#define check_access(thd, access, db, save_priv, no_grant, no_errors) false -#define check_table_access(thd, want_access, tables, no_errors) false -#define check_global_access(thd, want_access) false -#endif int mysql_backup_table(THD* thd, TABLE_LIST* table_list); int mysql_restore_table(THD* thd, TABLE_LIST* table_list); @@ -977,8 +977,7 @@ void filesort_free_buffers(TABLE *table); void change_double_for_sort(double nr,byte *to); int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); -uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week, - uint *year); +uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); TYPELIB *typelib(List<String> &strings); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index edcf4a823ed..14ebf475692 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -500,6 +500,8 @@ static uint set_maximum_open_files(uint max_file_limit); static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static void clean_up(bool print_message); static void clean_up_mutexes(void); +static int test_if_case_insensitive(const char *dir_name); +static void create_pid_file(); #ifndef EMBEDDED_LIBRARY /**************************************************************************** @@ -1061,7 +1063,7 @@ static void set_user(const char *user) } return; } - else if (!user) + if (!user) { if (!opt_bootstrap) { @@ -1483,16 +1485,7 @@ static void start_signal_handler(void) { // Save vm id of this process if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) - { - char buff[21]; - sprintf(buff,"%lu",(ulong) getpid()); - (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); // no signal handler } @@ -1778,16 +1771,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) /* Save pid to this process (or thread on Linux) */ if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) - { - char buff[21]; - ulong length= my_sprintf(buff, (buff,"%lu",(ulong) getpid())); - (void) my_write(pidFile, buff, length, MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); + #ifdef HAVE_STACK_TRACE_ON_SEGV if (opt_do_pstack) { @@ -2809,7 +2794,7 @@ default_service_handling(char **argv, } /* We must have servicename last */ *pos++= ' '; - strmake(pos, servicename, (uint) (end+2 - pos)); + (void) add_quoted_string(pos, servicename, end); if (Service.got_service_option(argv, "install")) { @@ -4649,7 +4634,7 @@ The minimum value for this variable is 4096.", 1, 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, - (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 16384, 0, 1, + (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1, 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", @@ -4667,7 +4652,7 @@ The minimum value for this variable is 4096.", {"thread_stack", OPT_THREAD_STACK, "The stack size for each thread.", (gptr*) &thread_stack, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, - 1024*32, ~0L, 0, 1024, 0}, + 1024L*128L, ~0L, 0, 1024, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for transactions to be stored in binary log", (gptr*) &global_system_variables.trans_alloc_block_size, @@ -4692,7 +4677,7 @@ The minimum value for this variable is 4096.", "The default week format used by WEEK() functions.", (gptr*) &global_system_variables.default_week_format, (gptr*) &max_system_variables.default_week_format, - 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, { "date-format", OPT_DATE_FORMAT, "The DATE format (For future).", (gptr*) &opt_date_time_formats[TIMESTAMP_DATE], @@ -5430,11 +5415,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: - if (!argument || - (my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) + if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) { struct hostent *ent; - if (argument || argument[0]) + if (argument[0]) ent=gethostbyname(argument); else { @@ -5844,6 +5828,18 @@ static void fix_paths(void) exit(1); } #endif /* HAVE_REPLICATION */ + + /* + Ensure that lower_case_table_names is set on system where we have case + insensitive names. If this is not done the users MyISAM tables will + get corrupted if accesses with names of different case. + */ + if (!lower_case_table_names && + test_if_case_insensitive(mysql_real_data_home) == 1) + { + sql_print_error("Warning: Setting lower_case_table_names=1 becasue file system %s is case insensitive", mysql_real_data_home); + lower_case_table_names= 1; + } } @@ -5997,6 +5993,61 @@ skipp: ; } /* find_bit_type */ +/* + Check if file system used for databases is case insensitive + + SYNOPSIS + test_if_case_sensitive() + dir_name Directory to test + + RETURN + -1 Don't know (Test failed) + 0 File system is case sensitive + 1 File system is case insensitive +*/ + +static int test_if_case_insensitive(const char *dir_name) +{ + int result= 0; + File file; + char buff[FN_REFLEN], buff2[FN_REFLEN]; + MY_STAT stat_info; + + fn_format(buff, glob_hostname, dir_name, ".lower-test", + MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); + fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST", + MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); + (void) my_delete(buff2, MYF(0)); + if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0) + { + sql_print_error("Warning: Can't create test file %s", buff); + return -1; + } + my_close(file, MYF(0)); + if (my_stat(buff2, &stat_info, MYF(0))) + result= 1; // Can access file + (void) my_delete(buff, MYF(MY_WME)); + return result; +} + + +/* Create file to store pid number */ + +static void create_pid_file() +{ + File file; + if ((file = my_create(pidfile_name,0664, + O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) + { + char buff[21], *end; + end= int2str((long) getpid(), buff, 10); + *end++= '\n'; + (void) my_write(file, (byte*) buff, (uint) (end-buff),MYF(MY_WME)); + (void) my_close(file, MYF(0)); + } +} + + /***************************************************************************** Instantiate templates *****************************************************************************/ diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index 25fc010d9a5..3e9d68d5fdb 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -496,9 +496,9 @@ BOOL NTService::IsService(LPCSTR ServiceName) BOOL ret_value=FALSE; SC_HANDLE service, scm; - if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)) + if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))) { - if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS ))) + if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS ))) { ret_value=TRUE; CloseServiceHandle(service); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 53a1c822b2f..f734a9a2334 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1461,9 +1461,10 @@ static SEL_ARG * get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type,Item *value) { - uint maybe_null=(uint) field->real_maybe_null(); + uint maybe_null=(uint) field->real_maybe_null(), copies; uint field_length=field->pack_length()+maybe_null; SEL_ARG *tree; + char *str, *str2; DBUG_ENTER("get_mm_leaf"); if (type == Item_func::LIKE_FUNC) @@ -1564,16 +1565,38 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, /* This happens when we try to insert a NULL field in a not null column */ DBUG_RETURN(&null_element); // cmp with NULL is never true } - // Get local copy of key - char *str= (char*) alloc_root(param->mem_root, - key_part->part_length+maybe_null); + /* Get local copy of key */ + copies= 1; + if (field->key_type() == HA_KEYTYPE_VARTEXT) + copies= 2; + str= str2= (char*) alloc_root(param->mem_root, + (key_part->part_length+maybe_null)*copies+1); if (!str) DBUG_RETURN(0); if (maybe_null) *str= (char) field->is_real_null(); // Set to 1 if null field->get_key_image(str+maybe_null,key_part->part_length, field->charset(),key_part->image_type); - if (!(tree=new SEL_ARG(field,str,str))) + if (copies == 2) + { + /* + The key is stored as 2 byte length + key + key doesn't match end space. In other words, a key 'X ' should match + all rows between 'X' and 'X ...' + */ + uint length= uint2korr(str+maybe_null); + str2= str+ key_part->part_length + maybe_null; + /* remove end space */ + while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ') + length--; + int2store(str+maybe_null, length); + /* Create key that is space filled */ + memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null); + bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null, + key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' '); + int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH); + } + if (!(tree=new SEL_ARG(field,str,str2))) DBUG_RETURN(0); // out of memory switch (type) { @@ -2039,7 +2062,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) } return 0; } - else if (!key2) + if (!key2) { key1->use_count--; key1->free_tree(); @@ -2798,7 +2821,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, param->range_count++; if (!tmp_min_flag && ! tmp_max_flag && (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && - (param->table->key_info[keynr].flags & HA_NOSAME) && + (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME && min_key_length == max_key_length && !memcmp(param->min_key,param->max_key,min_key_length)) tmp=1; // Max one record @@ -2954,7 +2978,8 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, { KEY *table_key=quick->head->key_info+quick->index; flag=EQ_RANGE; - if (table_key->flags & HA_NOSAME && key->part == table_key->key_parts-1) + if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && + key->part == table_key->key_parts-1) { if (!(table_key->flags & HA_NULL_PART_KEY) || !null_part_in_key(key, @@ -3000,7 +3025,7 @@ bool QUICK_RANGE_SELECT::unique_key_range() if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE) { KEY *key=head->key_info+index; - return ((key->flags & HA_NOSAME) && + return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && key->key_length == tmp->min_length); } } @@ -3036,6 +3061,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, QUICK_RANGE_SELECT *quick=new QUICK_RANGE_SELECT(thd, table, ref->key, 1); KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; + QUICK_RANGE *range; uint part; if (!quick) @@ -3049,18 +3075,18 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, if (cp_buffer_from_ref(ref)) { if (thd->is_fatal_error) - return 0; // out of memory + goto err; // out of memory return quick; // empty range } - QUICK_RANGE *range= new QUICK_RANGE(); - if (!range) + if (!(range= new QUICK_RANGE())) goto err; // out of memory range->min_key=range->max_key=(char*) ref->key_buff; range->min_length=range->max_length=ref->key_length; range->flag= ((ref->key_length == key_info->key_length && - (key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0); + (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) ? EQ_RANGE : 0); if (!(quick->key_parts=key_part=(KEY_PART *) alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))) diff --git a/sql/records.cc b/sql/records.cc index b29b113a1bc..cd1de5af6aa 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -118,11 +118,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->read_record=rr_sequential; table->file->rnd_init(); /* We can use record cache if we don't update dynamic length tables */ - if (use_record_cache > 0 || - (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || - !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || - (use_record_cache < 0 && - !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))) + if (!table->no_cache && + (use_record_cache > 0 || + (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || + !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || + (use_record_cache < 0 && + !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))) VOID(table->file->extra_opt(HA_EXTRA_CACHE, thd->variables.read_buff_size)); } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 0efe57af0b0..49c29ee1e9f 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -52,6 +52,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, const char* log_file_name, char* errmsg); +/* + All of the functions defined in this file which are not used (the ones to + handle failsafe) are not used; their code has not been updated for more than + one year now so should be considered as BADLY BROKEN. Do not enable it. + The used functions (to handle LOAD DATA FROM MASTER, plus some small + functions like register_slave()) are working. +*/ static int init_failsafe_rpl_thread(THD* thd) { @@ -418,7 +425,6 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, "Could not find slave event in log '%s'", (char*)log_file_name); - delete ev; return 0; } diff --git a/sql/set_var.cc b/sql/set_var.cc index 4140160a93b..4cf9f07b4ba 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -792,9 +792,8 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, /* If the string is "", delete old init command */ if (var && (new_length= var->value->str_value.length())) { - if (!(res= my_strdup_with_length(var->value->str_value.ptr(), - new_length, - MYF(0)))) + if (!(res= my_strdup_with_length((byte*) var->value->str_value.ptr(), + new_length, MYF(0)))) return 1; } /* @@ -2531,6 +2530,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var) } return 0; } + value= "unknown"; err: my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 94ed6410f30..ae040fd92ac 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -213,7 +213,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -272,8 +272,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 8e2e4fac919..b7f947d346e 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -266,8 +266,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 8f8d5dcabfb..9e2bb859a45 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -274,8 +274,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 9750b47ab7f..cffbdeeeca2 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -204,7 +204,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -263,8 +263,8 @@ character-set=latin1 "ZLIB: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "ZLIB: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index ed45006ad0d..34158b491b2 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -209,7 +209,7 @@ character-set=latin7 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga", "Ainult konstantsed suurused on lubatud SET klauslis", @@ -268,8 +268,8 @@ character-set=latin7 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 84ae6d995cf..9a2b3a5ec6a 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -204,7 +204,7 @@ character-set=latin1 "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord", "Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE", "Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO", -"Impossible d'initialiser les structures d'information de maître, vérifiez les permissions sur master.info", +"Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL", "Impossible de créer une tâche esclave, vérifiez les ressources système", "L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connections actives", "Seules les expressions constantes sont autorisées avec SET", @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 94b9476b0ff..95c00ec2dd9 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -204,7 +204,7 @@ character-set=greek "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -263,8 +263,8 @@ character-set=greek "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 67a20b1c63b..4a10797e1d1 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -265,8 +265,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index b2186baf558..2b8a7ea5632 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index aea9c84b6e6..752ed402190 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -206,7 +206,7 @@ character-set=ujis "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -265,8 +265,8 @@ character-set=ujis "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 69bf4043b44..8d98d5cb610 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -204,7 +204,7 @@ character-set=euckr "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -263,8 +263,8 @@ character-set=euckr "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 8abc62814ca..f1dd2cb8371 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index ed4540c377d..44705db0af5 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index d0891a8080d..622e127dc5e 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -208,7 +208,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -267,8 +267,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 341747620d9..a37f29b8a33 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -208,7 +208,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -267,8 +267,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 61c03f2f960..2dbe6b9184c 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -265,8 +265,8 @@ character-set=koi8r "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index ef9ffab981b..97bef4e1714 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -258,8 +258,8 @@ character-set=cp1250 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index daf9e0bd200..e841214ba1c 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -212,7 +212,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", +"Could not initialize master info structure, more error messages can be found in the MySQL error log", "Could not create slave thread, check system resources", "User %-.64s has already more than 'max_user_connections' active connections", "You may only use constant expressions with SET", @@ -271,8 +271,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 9acc80a2211..cdabd339e1e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index d8e3291a9f6..aab70294ec8 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d rad(er) kapades av group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index a336eb3e159..828c0a46cad 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -268,8 +268,8 @@ character-set=koi8u "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/slave.cc b/sql/slave.cc index 3f8a3c37618..42a1e4e9061 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1388,6 +1388,7 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname) 1 /* no auto events */, max_relay_log_size ? max_relay_log_size : max_binlog_size)) { + pthread_mutex_unlock(&rli->data_lock); sql_print_error("Failed in open_log() called from init_relay_log_info()"); DBUG_RETURN(1); } @@ -2351,7 +2352,9 @@ improper_arguments: %d timed_out: %d", static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) { DBUG_ENTER("init_slave_thread"); - thd->system_thread = thd->bootstrap = 1; + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? + SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; + thd->bootstrap= 1; thd->host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); @@ -4034,8 +4037,20 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s", sizeof(rli->event_relay_log_name)-1); flush_relay_log_info(rli); } - - // next log is hot + + /* + Now we want to open this next log. To know if it's a hot log (the one + being written by the I/O thread now) or a cold log, we can use + is_active(); if it is hot, we use the I/O cache; if it's cold we open + the file normally. But if is_active() reports that the log is hot, this + may change between the test and the consequence of the test. So we may + open the I/O cache whereas the log is now cold, which is nonsense. + To guard against this, we need to have LOCK_log. + */ + + DBUG_PRINT("info",("hot_log: %d",hot_log)); + if (!hot_log) /* if hot_log, we already have this mutex */ + pthread_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { #ifdef EXTRA_DEBUG @@ -4048,15 +4063,24 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s", /* Read pointer has to be at the start since we are the only - reader + reader. + We must keep the LOCK_log to read the 4 first bytes, as this is a hot + log (same as when we call read_log_event() above: for a hot log we + take the mutex). */ if (check_binlog_magic(cur_log,&errmsg)) + { + if (!hot_log) pthread_mutex_unlock(log_lock); goto err; + } + if (!hot_log) pthread_mutex_unlock(log_lock); continue; } + if (!hot_log) pthread_mutex_unlock(log_lock); /* - if we get here, the log was not hot, so we will have to - open it ourselves + if we get here, the log was not hot, so we will have to open it + ourselves. We are sure that the log is still not hot now (a log can get + from hot to cold, but not from cold to hot). No need for LOCK_log. */ #ifdef EXTRA_DEBUG sql_print_error("next log '%s' is not active", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2527edc1643..486d9df5393 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -697,6 +697,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, If cipher name is specified, we compare it to actual cipher in use. */ + X509 *cert; if (vio_type(vio) != VIO_TYPE_SSL || SSL_get_verify_result(ssl) != X509_V_OK) break; @@ -717,7 +718,11 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, } /* Prepare certificate (if exists) */ DBUG_PRINT("info",("checkpoint 1")); - X509* cert=SSL_get_peer_certificate(ssl); + if (!(cert= SSL_get_peer_certificate(ssl))) + { + user_access=NO_ACCESS; + break; + } DBUG_PRINT("info",("checkpoint 2")); /* If X509 issuer is speified, we check it... */ if (acl_user->x509_issuer) @@ -1246,6 +1251,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->user ? acl_user->user : "", acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); + thd->clear_error(); Query_log_event qinfo(thd, buff, query_length, 0); mysql_bin_log.write(&qinfo); DBUG_RETURN(0); @@ -1317,11 +1323,11 @@ static const char *calc_ip(const char *ip, long *val, char end) static void update_hostname(acl_host_and_ip *host, const char *hostname) { host->hostname=(char*) hostname; // This will not be modified! - if (hostname && + if (!hostname || (!(hostname=calc_ip(hostname,&host->ip,'/')) || !(hostname=calc_ip(hostname+1,&host->ip_mask,'\0')))) { - host->ip=host->ip_mask=0; // Not a masked ip + host->ip= host->ip_mask=0; // Not a masked ip } } diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 9858b403d27..f17c9781e8c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -58,8 +58,6 @@ #define EXTRA_ACL (1L << 29) #define NO_ACCESS (1L << 30) -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Defines to change the above bits to how things are stored in tables This is needed as the 'host' and 'db' table is missing a few privileges @@ -127,8 +125,6 @@ public: char *user,*db; }; - - /* prototypes */ bool hostname_requires_resolving(const char *hostname); @@ -153,7 +149,7 @@ my_bool grant_init(THD *thd); void grant_free(void); void grant_reload(THD *thd); bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, - uint show_command=0, bool dont_print_error=0); + uint show_command, bool dont_print_error); bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length, uint show_command=0); bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table); @@ -166,5 +162,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc); int mysql_drop_user(THD *thd, List <LEX_USER> &list); int mysql_revoke_all(THD *thd, List <LEX_USER> &list); -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ - +#ifdef NO_EMBEDDED_ACCESS_CHECKS +#define check_grant(A,B,C,D,E) 0 +#define check_grant_db(A,B) 0 +#endif diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index a6c24a25d6e..9e73e06d9c6 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -213,8 +213,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->is_float = 1; // we can't use variable decimals here return 1; } - else - return 0; + return 0; } for (str++; *(end - 1) == '0'; end--); // jump over zeros at the end if (str == end) // number was something like '123.000' @@ -229,11 +228,8 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->dval = atod(begin); return 1; } - else - return 0; } - else - return 0; + return 0; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5b347267adb..82e84f8ce49 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -513,8 +513,8 @@ void close_temporary_tables(THD *thd) if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ + thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); - qinfo.error_code=0; mysql_bin_log.write(&qinfo); } thd->temporary_tables=0; @@ -1752,6 +1752,19 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, const char *table_name=item->table_name; const char *name=item->field_name; uint length=(uint) strlen(name); + char name_buff[NAME_LEN+1]; + + if (db && lower_case_table_names) + { + /* + convert database to lower case for comparision. + We can't do this in Item_field as this would change the + 'name' of the item which may be used in the select list + */ + strmake(name_buff, db, sizeof(name_buff)-1); + my_casedn_str(files_charset_info, name_buff); + db= name_buff; + } if (table_name && table_name[0]) { /* Qualified field */ @@ -1969,7 +1982,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, while ( wild_num && (item= it++)) { if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && - ((Item_field*) item)->field_name[0] == '*') + ((Item_field*) item)->field_name[0] == '*' && + !((Item_field*) item)->field) { uint elem= fields.elements; if (insert_fields(thd,tables,((Item_field*) item)->db_name, diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index edc61acb117..4a517a04495 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1211,9 +1211,29 @@ void Query_cache::invalidate(char *db) if (query_cache_size > 0) { DUMP(this); - /* invalidate_table reduce list while only root of list remain */ - while (tables_blocks !=0 ) - invalidate_table(tables_blocks); + restart_search: + if (tables_blocks) + { + Query_cache_block *curr= tables_blocks; + Query_cache_block *next; + do + { + next= curr->next; + if (strcmp(db, (char*)(curr->table()->db())) == 0) + invalidate_table(curr); + /* + invalidate_table can freed block on which point 'next' (if + table of this block used only in queries which was deleted + by invalidate_table). As far as we do not allocate new blocks + and mark all headers of freed blocks as 'FREE' (even if they are + merged with other blocks) we can just test type of block + to be sure that block is not deleted + */ + if (next->type == Query_cache_block::FREE) + goto restart_search; + curr= next; + } while (curr != tables_blocks); + } } STRUCT_UNLOCK(&structure_guard_mutex); } @@ -2223,9 +2243,11 @@ void Query_cache::free_memory_block(Query_cache_block *block) { DBUG_ENTER("Query_cache::free_memory_block"); block->used=0; - DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", - (ulong) first_block, (ulong) block,block->pnext, - (ulong) block->pprev)); + block->type= Query_cache_block::FREE; // mark block as free in any case + DBUG_PRINT("qcache", + ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", + (ulong) first_block, (ulong) block, (ulong) block->pnext, + (ulong) block->pprev)); if (block->pnext != first_block && block->pnext->is_free()) block = join_free_blocks(block, block->pnext); diff --git a/sql/sql_class.h b/sql/sql_class.h index e81c2ba0110..2333a9ab369 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -711,7 +711,7 @@ public: long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table; - uint server_status,open_options; + uint server_status,open_options,system_thread; uint32 db_length; uint select_number; //number of select (used for EXPLAIN) /* variables.transaction_isolation is reset to this after each commit */ @@ -728,7 +728,7 @@ public: bool last_cuted_field; bool no_errors, password, is_fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - bool system_thread,in_lock_tables,global_read_lock; + bool in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; enum killed_state { NOT_KILLED=0, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED }; @@ -885,6 +885,11 @@ public: void update_charset(); }; +/* Flags for the THD::system_thread (bitmap) variable */ +#define SYSTEM_THREAD_DELAYED_INSERT 1 +#define SYSTEM_THREAD_SLAVE_IO 2 +#define SYSTEM_THREAD_SLAVE_SQL 4 + /* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) @@ -896,7 +901,7 @@ public: String *field_term,*enclosed,*line_term,*line_start,*escaped; bool opt_enclosed; bool dumpfile; - uint skip_lines; + ulong skip_lines; sql_exchange(char *name,bool dumpfile_flag); ~sql_exchange() {} }; @@ -1252,7 +1257,7 @@ class multi_delete :public select_result TABLE_LIST *delete_tables, *table_being_deleted; Unique **tempfiles; THD *thd; - ha_rows deleted; + ha_rows deleted, found; uint num_of_tables; int error; bool do_delete, transactional_tables, log_delayed, normal_tables; diff --git a/sql/sql_client.cc b/sql/sql_client.cc index 9f3063cde2d..49d0d3087ad 100644 --- a/sql/sql_client.cc +++ b/sql/sql_client.cc @@ -37,4 +37,3 @@ void my_net_local_init(NET *net) #endif } } - diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a057e0be967..2d636c51dd4 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -62,7 +62,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) ulong length; CHARSET_INFO *cs= (create && create->default_table_charset) ? create->default_table_charset : - thd->variables.collation_database; + thd->variables.collation_server; length= my_sprintf(buf,(buf, "default-character-set=%s\ndefault-collation=%s\n", cs->csname,cs->name)); @@ -101,7 +101,7 @@ static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) uint nbytes; bzero((char*) create,sizeof(*create)); - create->default_table_charset= global_system_variables.collation_database; + create->default_table_charset= thd->variables.collation_server; if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0) { IO_CACHE cache; @@ -289,13 +289,14 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) { thd->db_charset= (create_info && create_info->default_table_charset) ? create_info->default_table_charset : - global_system_variables.collation_database; + thd->variables.collation_server; thd->variables.collation_database= thd->db_charset; } if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + thd->clear_error(); mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -381,6 +382,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, query, query_length, 0); + thd->clear_error(); mysql_bin_log.write(&qinfo); } send_ok(thd,(ulong) deleted); @@ -660,7 +662,7 @@ bool mysql_change_db(THD *thd, const char *name) load_db_opt(thd, path, &create); thd->db_charset= create.default_table_charset ? create.default_table_charset : - global_system_variables.collation_database; + thd->variables.collation_server; thd->variables.collation_database= thd->db_charset; DBUG_RETURN(0); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 3abb09a5d60..03f952f3ff5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -135,14 +135,20 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, fields, all_fields, order) || !(sortorder=make_unireg_sortorder(order, &length)) || (table->sort.found_records = filesort(thd, table, sortorder, length, - (SQL_SELECT *) 0, HA_POS_ERROR, + select, HA_POS_ERROR, &examined_rows)) == HA_POS_ERROR) { delete select; free_underlaid_joins(thd, &thd->lex->select_lex); - DBUG_RETURN(-1); // This will force out message + DBUG_RETURN(-1); // This will force out message } + /* + Filesort has already found and selected the rows we want to delete, + so we don't need the where clause + */ + delete select; + select= 0; } init_read_record(&info,thd,table,select,1,1); @@ -204,6 +210,8 @@ cleanup: { if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -250,7 +258,7 @@ extern "C" int refposcmp2(void* arg, const void *a,const void *b) multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg) - : delete_tables(dt), thd(thd_arg), deleted(0), + : delete_tables(dt), thd(thd_arg), deleted(0), found(0), num_of_tables(num_of_tables_arg), error(0), do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0) { @@ -354,6 +362,7 @@ bool multi_delete::send_data(List<Item> &values) continue; table->file->position(table->record[0]); + found++; if (secure_counter < 0) { @@ -429,7 +438,7 @@ int multi_delete::do_deletes(bool from_send_error) if (from_send_error) { - /* Found out table number for 'table_being_deleted' */ + /* Found out table number for 'table_being_deleted*/ for (TABLE_LIST *aux=delete_tables; aux != table_being_deleted; aux=aux->next) @@ -439,6 +448,8 @@ int multi_delete::do_deletes(bool from_send_error) table_being_deleted = delete_tables; do_delete= 0; + if (!found) + DBUG_RETURN(0); for (table_being_deleted=table_being_deleted->next; table_being_deleted ; table_being_deleted=table_being_deleted->next, counter++) @@ -508,6 +519,8 @@ bool multi_delete::send_eof() { if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && !normal_tables) @@ -618,6 +631,7 @@ end: { if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, thd->tmp_table); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1de86f486b4..88585db34ce 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -366,6 +366,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, { if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -630,7 +632,7 @@ public: thd.lex->current_select= 0; /* for my_message_sql */ bzero((char*) &thd.net,sizeof(thd.net)); // Safety - thd.system_thread=1; + thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); @@ -1495,6 +1497,8 @@ bool select_insert::send_eof() /* Write to binlog before commiting transaction */ if (mysql_bin_log.is_open()) { + if (!error) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, table->file->has_transactions()); mysql_bin_log.write(&qinfo); @@ -1508,7 +1512,6 @@ bool select_insert::send_eof() ::send_error(thd); DBUG_RETURN(1); } - char buff[160]; if (info.handle_duplicates == DUP_IGNORE) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 41d9f0b6c4d..2f8a979b5ee 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -72,10 +72,11 @@ public: }; static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, - List<Item> &fields, READ_INFO &read_info); + List<Item> &fields, READ_INFO &read_info, + ulong skip_lines); static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List<Item> &fields, READ_INFO &read_info, - String &enclosed); + String &enclosed, ulong skip_lines); int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List<Item> &fields, enum enum_duplicates handle_duplicates, @@ -85,8 +86,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, File file; TABLE *table; int error; - String *field_term=ex->field_term,*escaped=ex->escaped, - *enclosed=ex->enclosed; + String *field_term=ex->field_term,*escaped=ex->escaped; + String *enclosed=ex->enclosed; bool is_fifo=0; #ifndef EMBEDDED_LIBRARY LOAD_FILE_INFO lf_info; @@ -95,6 +96,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, /* If no current database, use database where table is located */ char *tdb= thd->db ? thd->db : db; bool transactional_table, log_delayed; + ulong skip_lines= ex->skip_lines; DBUG_ENTER("mysql_load"); #ifdef EMBEDDED_LIBRARY @@ -254,16 +256,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; - if (ex->line_term->length() && field_term->length()) + /* Skip lines if there is a line terminator */ + if (ex->line_term->length()) { - // ex->skip_lines needs to be preserved for logging - uint skip_lines = ex->skip_lines; - while (skip_lines--) + /* ex->skip_lines needs to be preserved for logging */ + while (skip_lines > 0) { + skip_lines--; if (read_info.next_line()) break; } } + if (!(error=test(read_info.error))) { uint save_time_stamp=table->time_stamp; @@ -279,9 +283,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->deactivate_non_unique_index((ha_rows) 0); table->copy_blobs=1; if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info); + error=read_fixed_length(thd,info,table,fields,read_info, + skip_lines); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed); + error=read_sep_field(thd,info,table,fields,read_info,*enclosed, + skip_lines); if (table->file->extra(HA_EXTRA_NO_CACHE)) error=1; /* purecov: inspected */ if (table->file->activate_all_index(thd)) @@ -290,7 +296,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->time_stamp=save_time_stamp; table->next_number_field=0; } - if (file >= 0) my_close(file,MYF(0)); + if (file >= 0) + my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -392,7 +399,7 @@ err: static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, - READ_INFO &read_info) + READ_INFO &read_info, ulong skip_lines) { List_iterator_fast<Item> it(fields); Item_field *sql_field; @@ -412,6 +419,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, thd->send_kill_message(); DBUG_RETURN(1); } + if (skip_lines) + { + /* + We could implement this with a simple seek if: + - We are not using DATA INFILE LOCAL + - escape character is "" + - line starting prefix is "" + */ + skip_lines--; + continue; + } it.rewind(); byte *pos=read_info.row_start; #ifdef HAVE_purify @@ -482,7 +500,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List<Item> &fields, READ_INFO &read_info, - String &enclosed) + String &enclosed, ulong skip_lines) { List_iterator_fast<Item> it(fields); Item_field *sql_field; @@ -533,6 +551,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, } if (read_info.error) break; + if (skip_lines) + { + if (!--skip_lines) + thd->cuted_fields= 0L; // Reset warnings + continue; + } if (sql_field) { // Last record if (sql_field == (Item_field*) fields.head()) @@ -872,7 +896,18 @@ found_eof: } /* -** One can't use fixed length with multi-byte charset ** + Read a row with fixed length. + + NOTES + The row may not be fixed size on disk if there are escape + characters in the file. + + IMPLEMENTATION NOTE + One can't use fixed length with multi-byte charset ** + + RETURN + 0 ok + 1 error */ int READ_INFO::read_fixed_length() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5bafe839486..2232b7816ed 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -63,14 +63,9 @@ extern "C" int gethostname(char *name, int namelen); static int check_for_max_user_connections(THD *thd, USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc); static bool check_db_used(THD *thd,TABLE_LIST *tables); -#ifndef NO_EMBEDDED_ACCESS_CHECKS static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res); -#else -#define check_merge_table_access(thd, db, tables) false -#define single_table_command_access(thd, privilege, tables, res) false -#endif static void remove_escape(char *name); static void refresh_status(void); static bool append_file_to_dir(THD *thd, char **filename_ptr, @@ -189,7 +184,6 @@ end: } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if user exist and password supplied is correct. @@ -222,6 +216,11 @@ int check_user(THD *thd, enum enum_server_command command, { DBUG_ENTER("check_user"); +#ifdef NO_EMBEDDED_ACCESS_CHECKS + thd->master_access= GLOBAL_ACLS; // Full rights + return 0; +#else + my_bool opt_secure_auth_local; pthread_mutex_lock(&LOCK_global_system_variables); opt_secure_auth_local= opt_secure_auth; @@ -346,7 +345,7 @@ int check_user(THD *thd, enum enum_server_command command, } } else - send_ok(thd); + send_ok(thd); thd->password= test(passwd_len); // remember for error messages /* Ready to handle queries */ DBUG_RETURN(0); @@ -367,11 +366,9 @@ int check_user(THD *thd, enum enum_server_command command, thd->host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); DBUG_RETURN(-1); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ - - /* Check for maximum allowable user connections, if the mysqld server is started with corresponding variable that is greater then 0. @@ -522,7 +519,6 @@ bool is_update_query(enum enum_sql_command command) return uc_update_queries[command]; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if maximum queries per hour limit has been reached returns 0 if OK. @@ -541,6 +537,9 @@ static bool check_mqh(THD *thd, uint check_command) DBUG_ENTER("check_mqh"); DBUG_ASSERT(uc != 0); +#ifdef NO_EMBEDDED_ACCESS_CHECKS + DBUG_RETURN(0); +#else /* If more than a hour since last check, reset resource checking */ if (check_time - uc->intime >= 3600) { @@ -574,12 +573,13 @@ static bool check_mqh(THD *thd, uint check_command) } end: DBUG_RETURN(error); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) { - +#ifndef NO_EMBEDDED_ACCESS_CHECKS (void) pthread_mutex_lock(&LOCK_user_conn); if (lu) // for GRANT { @@ -603,7 +603,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) { for (uint idx=0;idx < hash_user_connections.records; idx++) { - USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, idx); + USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, + idx); if (get_them) get_mqh(uc->user,uc->host,uc); uc->questions=0; @@ -612,8 +613,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) } } (void) pthread_mutex_unlock(&LOCK_user_conn); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ /* Perform handshake, authorize client and update thd ACL variables. @@ -1075,7 +1076,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1); thd->query[length] = '\0'; thd->query_id=query_id++; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END)) { thd->net.error = 0; @@ -1083,7 +1083,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); break; } -#endif mysql_parse(thd,thd->query,length); close_thread_tables(thd); // Free tables if (thd->is_fatal_error) @@ -1147,12 +1146,10 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) DBUG_RETURN(1); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege,0,0)) goto err; - if (grant_option && check_grant(thd, SELECT_ACL, table_list)) + if (grant_option && check_grant(thd, SELECT_ACL, table_list, 0, 0)) goto err; -#endif thd->free_list = 0; thd->query_length=(uint) strlen(tbl_name); thd->query = tbl_name; @@ -1459,13 +1456,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_casedn_str(files_charset_info, table_list.real_name); remove_escape(table_list.real_name); // This can't have wildcards -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access,0,0)) break; table_list.grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2)) + if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0)) break; -#endif /*DONT_ALLOW_SHOW_COMMANDS*/ mysqld_list_fields(thd,&table_list,fields); free_items(thd->free_list); break; @@ -1609,19 +1604,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; case COM_PROCESS_INFO: statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; -#endif mysql_log.write(thd,command,NullS); mysqld_list_processes(thd, -#ifndef NO_EMBEDDED_ACCESS_CHECKS thd->master_access & PROCESS_ACL ? - NullS : thd->priv_user -#else - NullS -#endif - ,0); + NullS : thd->priv_user, 0); break; case COM_PROCESS_KILL: { @@ -1834,6 +1822,7 @@ mysql_execute_command(THD *thd) } } if (&lex->select_lex != lex->all_selects_list && + lex->sql_command != SQLCOM_CREATE_TABLE && lex->unit.create_total_list(thd, lex, &tables, 0)) DBUG_RETURN(0); @@ -1842,11 +1831,7 @@ mysql_execute_command(THD *thd) Except for the replication thread and the 'super' users. */ if (opt_readonly && - !(thd->slave_thread -#ifndef NO_EMBEDDED_ACCESS_CHECKS - || (thd->master_access & SUPER_ACL) -#endif - ) && + !(thd->slave_thread || (thd->master_access & SUPER_ACL)) && (uc_update_queries[lex->sql_command] > 0)) { send_error(thd, ER_CANT_UPDATE_WITH_READLOCK); @@ -1858,7 +1843,6 @@ mysql_execute_command(THD *thd) case SQLCOM_SELECT: { select_result *result=lex->result; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (tables) { res=check_table_access(thd, @@ -1874,7 +1858,6 @@ mysql_execute_command(THD *thd) res=0; break; // Error message is given } -#endif /* In case of single SELECT unit->global_parameters points on first SELECT TODO: move counters to SELECT_LEX @@ -2111,7 +2094,6 @@ mysql_execute_command(THD *thd) { if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ if (grant_option) @@ -2119,12 +2101,11 @@ mysql_execute_command(THD *thd) /* Check that the first table has CREATE privilege */ TABLE_LIST *tmp_table_list=tables->next; tables->next=0; - bool error=check_grant(thd,CREATE_ACL,tables); + bool error=check_grant(thd,CREATE_ACL,tables,0,0); tables->next=tmp_table_list; if (error) goto error; } -#endif if (strlen(tables->real_name) > NAME_LEN) { net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name); @@ -2147,43 +2128,34 @@ mysql_execute_command(THD *thd) case SQLCOM_CREATE_TABLE: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* Skip first table, which is the table we are creating */ + TABLE_LIST *create_table= tables; + tables= tables->next; + lex->select_lex.table_list.first= (byte*) (tables); + create_table->next= 0; + if (&lex->select_lex != lex->all_selects_list && + lex->unit.create_total_list(thd, lex, &tables, 0)) + DBUG_VOID_RETURN; + ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? CREATE_TMP_ACL : CREATE_ACL); -#endif - if (!tables->db) - tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_access(thd,want_priv,tables->db,&tables->grant.privilege,0,0) || - check_merge_table_access(thd, tables->db, + if (check_access(thd, want_priv, create_table->db, + &create_table->grant.privilege, 0, 0) || + check_merge_table_access(thd, create_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) goto error; /* purecov: inspected */ - if (grant_option && want_priv != CREATE_TMP_ACL) - { - /* Check that the first table has CREATE privilege */ - TABLE_LIST *tmp_table_list=tables->next; - tables->next=0; - bool error=check_grant(thd, want_priv, tables); - tables->next=tmp_table_list; - if (error) + if (grant_option && want_priv != CREATE_TMP_ACL && + check_grant(thd, want_priv, create_table,0,0)) goto error; - } -#endif - if (strlen(tables->real_name) > NAME_LEN) - { - net_printf(thd, ER_WRONG_TABLE_NAME, tables->alias); - res=0; - break; - } #ifndef HAVE_READLINK lex->create_info.data_file_name=lex->create_info.index_file_name=0; #else /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &lex->create_info.data_file_name, - tables->real_name) || + create_table->real_name) || append_file_to_dir(thd,&lex->create_info.index_file_name, - tables->real_name)) + create_table->real_name)) { res=-1; break; @@ -2207,49 +2179,42 @@ mysql_execute_command(THD *thd) select_result *result; if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && - find_real_table_in_list(tables->next, tables->db, tables->real_name)) + find_real_table_in_list(tables, create_table->db, + create_table->real_name)) { - net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name); + net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); DBUG_RETURN(-1); } -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables->next) - { - if (check_table_access(thd, SELECT_ACL, tables->next,0)) - goto error; // Error message is given - } -#endif + if (tables && check_table_access(thd, SELECT_ACL, tables,0)) + goto error; // Error message is given select_lex->options|= SELECT_NO_UNLOCK; unit->offset_limit_cnt= select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+ select_lex->offset_limit; if (unit->select_limit_cnt < select_lex->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; // No limit + unit->select_limit_cnt= HA_POS_ERROR; // No limit - /* Skip first table, which is the table we are creating */ - lex->select_lex.table_list.first= - (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next); - if (!(res=open_and_lock_tables(thd,tables->next))) + if (!(res=open_and_lock_tables(thd,tables))) { - if ((result=new select_create(tables->db ? tables->db : thd->db, - tables->real_name, &lex->create_info, + res= -1; // If error + if ((result=new select_create(create_table->db, + create_table->real_name, + &lex->create_info, lex->create_list, lex->key_list, select_lex->item_list,lex->duplicates))) res=handle_select(thd, lex, result); - else - res= -1; } } else // regular create { if (lex->name) - res= mysql_create_like_table(thd, tables, &lex->create_info, + res= mysql_create_like_table(thd, create_table, &lex->create_info, (Table_ident *)lex->name); else { - res= mysql_create_table(thd,tables->db ? tables->db : thd->db, - tables->real_name, &lex->create_info, + res= mysql_create_table(thd,create_table->db, + create_table->real_name, &lex->create_info, lex->create_list, lex->key_list,0,0,0); // do logging } @@ -2261,12 +2226,10 @@ mysql_execute_command(THD *thd) case SQLCOM_CREATE_INDEX: if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INDEX_ACL,tables)) + if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0)) goto error; -#endif thd->slow_command=TRUE; if (end_active_trans(thd)) res= -1; @@ -2334,10 +2297,9 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (grant_option) { - if (check_grant(thd,ALTER_ACL,tables)) + if (check_grant(thd,ALTER_ACL,tables,0,0)) goto error; if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) { // Rename of table @@ -2346,11 +2308,10 @@ mysql_execute_command(THD *thd) tmp_table.real_name=lex->name; tmp_table.db=select_lex->db; tmp_table.grant.privilege=priv; - if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables)) + if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables,0,0)) goto error; } } -#endif /* Don't yet allow changing of symlinks with ALTER TABLE */ lex->create_info.data_file_name=lex->create_info.index_file_name=0; /* ALTER TABLE ends previous transaction */ @@ -2378,7 +2339,6 @@ mysql_execute_command(THD *thd) TABLE_LIST *table; if (check_db_used(thd,tables)) goto error; -#ifndef NO_EMBEDDED_ACCESS_CHECKS for (table=tables ; table ; table=table->next->next) { if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, @@ -2392,14 +2352,13 @@ mysql_execute_command(THD *thd) old_list=table[0]; new_list=table->next[0]; old_list.next=new_list.next=0; - if (check_grant(thd,ALTER_ACL,&old_list) || + if (check_grant(thd,ALTER_ACL,&old_list,0,0) || (!test_all_bits(table->next->grant.privilege, INSERT_ACL | CREATE_ACL) && - check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list))) + check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list,0,0))) goto error; } } -#endif query_cache_invalidate3(thd, tables, 0); if (end_active_trans(thd)) res= -1; @@ -2550,12 +2509,10 @@ mysql_execute_command(THD *thd) res= -1; break; case SQLCOM_UPDATE_MULTI: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; - if (grant_option && check_grant(thd,UPDATE_ACL,tables)) + if (grant_option && check_grant(thd,UPDATE_ACL,tables,0,0)) goto error; -#endif if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2585,16 +2542,12 @@ mysql_execute_command(THD *thd) case SQLCOM_REPLACE: case SQLCOM_INSERT: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0); ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL | update); if (single_table_command_access(thd, privilege, tables, &res)) goto error; -#else - my_bool update=(lex->value_list.elements ? 1 : 0); -#endif if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2610,12 +2563,10 @@ mysql_execute_command(THD *thd) case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { - /* Check that we have modify privileges for the first table and select privileges for the rest */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS { ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); @@ -2623,14 +2574,18 @@ mysql_execute_command(THD *thd) tables->next=0; if (check_access(thd, privilege, tables->db,&tables->grant.privilege,0,0) || - (grant_option && check_grant(thd, privilege, tables))) + (grant_option && check_grant(thd, privilege, tables,0,0))) goto error; tables->next=save_next; if ((res=check_table_access(thd, SELECT_ACL, save_next,0))) goto error; } -#endif + + /* Fix lock for first table */ + if (tables->lock_type == TL_WRITE_DELAYED) + tables->lock_type= TL_WRITE; + /* Don't unlock tables until command is written to binary log */ select_lex->options|= SELECT_NO_UNLOCK; @@ -2664,12 +2619,10 @@ mysql_execute_command(THD *thd) break; } case SQLCOM_TRUNCATE: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,DELETE_ACL,tables)) + if (grant_option && check_grant(thd,DELETE_ACL,tables,0,0)) goto error; -#endif /* Don't allow this within a transaction because we want to use re-generate table @@ -2683,12 +2636,10 @@ mysql_execute_command(THD *thd) break; case SQLCOM_DELETE: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (single_table_command_access(thd, DELETE_ACL, tables, &res)) goto error; // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); -#endif res = mysql_delete(thd,tables, select_lex->where, (ORDER*) select_lex->order_list.first, select_lex->select_limit, select_lex->options); @@ -2810,12 +2761,10 @@ mysql_execute_command(THD *thd) case SQLCOM_DROP_INDEX: if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INDEX_ACL,tables)) + if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0)) goto error; -#endif if (end_active_trans(thd)) res= -1; else @@ -2833,18 +2782,11 @@ mysql_execute_command(THD *thd) break; #endif case SQLCOM_SHOW_PROCESSLIST: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; -#endif mysqld_list_processes(thd, -#ifndef NO_EMBEDDED_ACCESS_CHECKS thd->master_access & PROCESS_ACL ? NullS : - thd->priv_user -#else - NullS -#endif - ,lex->verbose); + thd->priv_user,lex->verbose); break; case SQLCOM_SHOW_STORAGE_ENGINES: res= mysqld_show_storage_engines(thd); @@ -2870,10 +2812,8 @@ mysql_execute_command(THD *thd) goto error; #else { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0)) goto error; -#endif res= mysqld_show_logs(thd); break; } @@ -2897,7 +2837,6 @@ mysql_execute_command(THD *thd) net_printf(thd,ER_WRONG_DB_NAME, db); goto error; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ if (!thd->col_access && check_grant_db(thd,db)) @@ -2908,7 +2847,6 @@ mysql_execute_command(THD *thd) db); goto error; } -#endif /* grant is checked in mysqld_show_tables */ if (select_lex->options & SELECT_DESCRIBE) res= mysqld_extend_show_tables(thd,db, @@ -2942,13 +2880,11 @@ mysql_execute_command(THD *thd) } remove_escape(db); // Fix escaped '_' remove_escape(tables->real_name); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ tables->grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,tables,2)) + if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0)) goto error; -#endif res= mysqld_show_fields(thd,tables, (lex->wild ? lex->wild->ptr() : NullS), lex->verbose); @@ -2971,13 +2907,11 @@ mysql_execute_command(THD *thd) remove_escape(tables->real_name); if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ tables->grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,tables,2)) + if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0)) goto error; -#endif res= mysqld_show_keys(thd,tables); break; } @@ -2988,7 +2922,6 @@ mysql_execute_command(THD *thd) case SQLCOM_LOAD: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS uint privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); @@ -3005,11 +2938,11 @@ mysql_execute_command(THD *thd) send_error(thd,ER_NOT_ALLOWED_COMMAND); goto error; } - if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0,0) || - grant_option && check_grant(thd,privilege,tables)) + if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0, + 0) || + grant_option && check_grant(thd,privilege,tables,0,0)) goto error; } -#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ res=mysql_load(thd, lex->exchange, tables, lex->field_list, lex->duplicates, (bool) lex->local_file, lex->lock_option); break; @@ -3249,13 +3182,14 @@ mysql_execute_command(THD *thd) if (grant_option && check_grant(thd, (lex->grant | lex->grant_tot_col | GRANT_ACL), - tables)) + tables,0,0)) goto error; if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE)) && mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -3274,6 +3208,7 @@ mysql_execute_command(THD *thd) { if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -3708,7 +3643,6 @@ error: } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check grants for commands which work only with one table and all other tables belong to subselects. @@ -3729,23 +3663,23 @@ static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res) { - if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0)) - return 1; + if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0)) + return 1; - // Show only 1 table for check_grant - TABLE_LIST *subselects_tables= tables->next; - tables->next= 0; - if (grant_option && check_grant(thd, privilege, tables)) - return 1; + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, privilege, tables, 0, 0)) + return 1; - // check rights on tables of subselect (if exists) - if (subselects_tables) - { - tables->next= subselects_tables; - if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0))) - return 1; - } - return 0; + // check rights on tables of subselect (if exists) + if (subselects_tables) + { + tables->next= subselects_tables; + if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0))) + return 1; + } + return 0; } @@ -3788,6 +3722,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(TRUE); /* purecov: tested */ } +#ifdef NO_EMBEDDED_ACCESS_CHECKS + DBUG_RETURN(0); +#else if ((thd->master_access & want_access) == want_access) { /* @@ -3837,6 +3774,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, thd->priv_host, db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -3861,6 +3799,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool check_global_access(THD *thd, ulong want_access) { +#ifdef NO_EMBEDDED_ACCESS_CHECKS + return 0; +#else char command[128]; if ((thd->master_access & want_access)) return 0; @@ -3868,6 +3809,7 @@ bool check_global_access(THD *thd, ulong want_access) net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR, command); return 1; +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -3932,7 +3874,6 @@ static bool check_merge_table_access(THD *thd, char *db, return error; } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ static bool check_db_used(THD *thd,TABLE_LIST *tables) { @@ -4048,7 +3989,9 @@ mysql_init_query(THD *thd, bool lexonly) thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; thd->is_fatal_error= thd->rand_used= 0; - thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | + SERVER_QUERY_NO_INDEX_USED | + SERVER_QUERY_NO_GOOD_INDEX_USED); thd->tmp_table_used= 0; if (opt_bin_log) reset_dynamic(&thd->user_var_events); @@ -4203,9 +4146,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) else { mysql_execute_command(thd); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ query_cache_end_of_result(&thd->net); -#endif } } } @@ -4213,7 +4154,6 @@ mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ query_cache_abort(&thd->net); if (thd->lex->sphead) { @@ -4222,7 +4162,6 @@ mysql_parse(THD *thd, char *inBuf, uint length) delete thd->lex->sphead; thd->lex->sphead= NULL; } -#endif } thd->proc_info="freeing items"; free_items(thd->free_list); /* Free strings used by items */ @@ -4272,7 +4211,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, if (default_value) { - if (default_value->type() == Item::NULL_ITEM) + if (type == FIELD_TYPE_TIMESTAMP) + { + net_printf(thd, ER_INVALID_DEFAULT, field_name); + DBUG_RETURN(1); + } + else if (default_value->type() == Item::NULL_ITEM) { default_value=0; if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == @@ -4937,10 +4881,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, UNLOCK_ACTIVE_MI; } #endif -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (options & REFRESH_USER_RESOURCES) reset_mqh(thd,(LEX_USER *) NULL); -#endif if (write_to_binlog) *write_to_binlog= tmp_write_to_binlog; return result; @@ -4975,18 +4917,14 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if ((thd->master_access & SUPER_ACL) || !strcmp(thd->user,tmp->user)) -#endif { tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); error=0; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS else error=ER_KILL_DENIED_ERROR; -#endif pthread_mutex_unlock(&tmp->LOCK_delete); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index bf7da934a2d..2897af0b87f 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -545,7 +545,7 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt, if (check_access(thd,privilege,table_list->db, &table_list->grant.privilege,0,0) || - (grant_option && check_grant(thd,privilege,table_list))) + (grant_option && check_grant(thd,privilege,table_list,0,0))) DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) @@ -600,7 +600,7 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,UPDATE_ACL,table_list->db, &table_list->grant.privilege,0,0) || - (grant_option && check_grant(thd,UPDATE_ACL,table_list))) + (grant_option && check_grant(thd,UPDATE_ACL,table_list,0,0))) DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 5ef8d5d1c1d..29b4f2f4a01 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -81,6 +81,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) { if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index edc897aa1fa..b2c1ef1ea8f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1121,8 +1121,21 @@ JOIN::exec() if (select_options & SELECT_DESCRIBE) { - if (!order && !no_order) - order=group_list; + /* + Check if we managed to optimize ORDER BY away and don't use temporary + table to resolve ORDER BY: in that case, we only may need to do + filesort for GROUP BY. + */ + if (!order && !no_order && (!skip_sort_order || !need_tmp)) + { + /* + Reset 'order' to 'group_list' and reinit variables describing + 'order' + */ + order= group_list; + simple_order= simple_group; + skip_sort_order= 0; + } if (order && (const_tables == tables || ((simple_order || skip_sort_order) && @@ -1861,7 +1874,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, } while (keyuse->table == table && keyuse->key == key); if (eq_part.is_prefix(table->key_info[key].key_parts) && - (table->key_info[key].flags & HA_NOSAME) && + ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) && !table->fulltext_searched) { if (const_ref == eq_part) @@ -2345,10 +2359,6 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) } } } - /* Mark that we can optimize LEFT JOIN */ - if (key_field->val->type() == Item::NULL_ITEM && - !key_field->field->real_maybe_null()) - key_field->field->table->reginfo.not_exists_optimize=1; } @@ -2447,15 +2457,28 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, SELECT_LEX *select_lex) { uint and_level,i,found_eq_constant; - KEY_FIELD *key_fields,*end; + KEY_FIELD *key_fields, *end, *field; if (!(key_fields=(KEY_FIELD*) thd->alloc(sizeof(key_fields[0])* (thd->lex->current_select->cond_count+1)*2))) return TRUE; /* purecov: inspected */ - and_level=0; end=key_fields; + and_level= 0; + field= end= key_fields; + if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) + return TRUE; if (cond) + { add_key_fields(join_tab,&end,&and_level,cond,normal_tables); + for (; field != end ; field++) + { + add_key_part(keyuse,field); + /* Mark that we can optimize LEFT JOIN */ + if (field->val->type() == Item::NULL_ITEM && + !field->field->real_maybe_null()) + field->field->table->reginfo.not_exists_optimize=1; + } + } for (i=0 ; i < tables ; i++) { if (join_tab[i].on_expr) @@ -2464,10 +2487,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, join_tab[i].table->map); } } - if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) - return TRUE; /* fill keyuse with found key parts */ - for (KEY_FIELD *field=key_fields ; field != end ; field++) + for ( ; field != end ; field++) add_key_part(keyuse,field); if (select_lex->ftfunc_list->elements) @@ -2717,7 +2738,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, !found_ref_or_null) { /* use eq key */ max_key_part= (uint) ~0; - if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) + if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) == HA_NOSAME) { tmp=prev_record_reads(join,found_ref); records=1.0; @@ -3230,9 +3252,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, return 0; if (j->type == JT_CONST) j->table->const_table= 1; - else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) - != HA_NOSAME) || keyparts != keyinfo->key_parts || - null_ref_key) + else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) != HA_NOSAME) || + keyparts != keyinfo->key_parts || null_ref_key) { /* Must read with repeat */ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF; @@ -4053,6 +4075,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, } result->send_eof(); // Should be safe } + /* Update results for FOUND_ROWS */ + join->thd->limit_found_rows= join->thd->examined_row_count= 0; DBUG_RETURN(0); } @@ -6766,7 +6790,7 @@ part_of_refkey(TABLE *table,Field *field) for (uint part=0 ; part < ref_parts ; part++,key_part++) if (field->eq(key_part->field) && - !(key_part->key_part_flag & HA_PART_KEY)) + !(key_part->key_part_flag & HA_PART_KEY_SEG)) return table->reginfo.join_tab->ref.items[part]; } return (Item*) 0; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 023f55c177f..3dfef4b7189 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -384,11 +384,23 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, #ifdef USE_SYMDIR char *ext; if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) + { + /* Only show the sym file if it points to a directory */ + char buff[FN_REFLEN], *end; + MY_STAT status; *ext=0; /* Remove extension */ + unpack_dirname(buff, file->name); + end= strend(buff); + if (end != buff && end[-1] == FN_LIBCHAR) + end[-1]= 0; // Remove end FN_LIBCHAR + if (!my_stat(buff, &status, MYF(0)) || + !MY_S_ISDIR(status.st_mode)) + continue; + } else #endif { - if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) || + if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) || (wild && wild_compare(file->name,wild,0))) continue; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 38e14de2245..0b48ae9bc2e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -257,6 +257,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, query_cache_invalidate3(thd, tables, 0); if (!dont_log_query && mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, tmp_table_deleted && !some_tables_deleted); mysql_bin_log.write(&qinfo); @@ -306,10 +307,10 @@ static int sort_keys(KEY *a, KEY *b) { if (!(b->flags & HA_NOSAME)) return -1; - if ((a->flags ^ b->flags) & HA_NULL_PART_KEY) + if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) { /* Sort NOT NULL keys before other keys */ - return (a->flags & HA_NULL_PART_KEY) ? 1 : -1; + return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; } if (a->name == primary_key_name) return -1; @@ -984,8 +985,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, thd->tmp_table_used= 1; } if (!tmp_table && !no_log && mysql_bin_log.is_open()) - // Must be written before unlock { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & HA_LEX_CREATE_TMP_TABLE)); @@ -2072,6 +2073,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, { if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2454,6 +2456,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2584,6 +2587,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->proc_info="end"; if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f256506593e..2f4c6b55963 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -359,6 +359,8 @@ int mysql_update(THD *thd, { if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -480,7 +482,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), - do_update(1), trans_safe(0) + do_update(1), trans_safe(0), transactional_tables(1) {} @@ -584,6 +586,27 @@ int multi_update::prepare(List<Item> ¬_used_values, for (i=0 ; i < table_count ; i++) set_if_bigger(max_fields, fields_for_table[i]->elements); copy_field= new Copy_field[max_fields]; + + /* + Mark all copies of tables that are updates to ensure that + init_read_record() will not try to enable a cache on them + + The problem is that for queries like + + UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a; + + the row buffer may contain things that doesn't match what is on disk + which will cause an error when reading a row. + (This issue is mostly relevent for MyISAM tables) + */ + for (table_ref= all_tables; table_ref; table_ref=table_ref->next) + { + TABLE *table=table_ref->table; + if (!(tables_to_update & table->map) && + find_real_table_in_list(update_tables, table_ref->db, + table_ref->real_name)) + table->no_cache= 1; // Disable row cache + } DBUG_RETURN(thd->is_fatal_error != 0); } @@ -743,7 +766,7 @@ multi_update::~multi_update() { TABLE_LIST *table; for (table= update_tables ; table; table= table->next) - table->table->no_keyread=0; + table->table->no_keyread= table->table->no_cache= 0; if (tmp_tables) { @@ -878,8 +901,11 @@ int multi_update::do_updates(bool from_send_error) ha_rows org_updated; TABLE *table; DBUG_ENTER("do_updates"); + - do_update= 0; // Don't retry this function + do_update= 0; // Don't retry this function + if (!found) + DBUG_RETURN(0); for (cur_table= update_tables; cur_table ; cur_table= cur_table->next) { table = cur_table->table; @@ -1005,6 +1031,8 @@ bool multi_update::send_eof() { if (mysql_bin_log.is_open()) { + if (local_error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && trans_safe) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dce3ed1ce48..bd73762c5a7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -629,9 +629,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %left SHIFT_LEFT SHIFT_RIGHT %left '-' '+' %left '*' '/' '%' DIV_SYM MOD_SYM -%left NEG '~' %left XOR %left '^' +%left NEG '~' %right NOT %right BINARY COLLATE_SYM @@ -6739,6 +6739,7 @@ order_or_limit: union_option: /* empty */ {} + | DISTINCT {} | ALL {Select->master_unit()->union_option|= UNION_ALL;}; singlerow_subselect: diff --git a/sql/table.cc b/sql/table.cc index 7c12762d9c4..912c133e571 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -507,14 +507,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) { /* - If the UNIQUE key don't have NULL columns, declare this as - a primary key. + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. */ primary_key=key; for (i=0 ; i < keyinfo->key_parts ;i++) { - if (!key_part[i].fieldnr || - outparam->field[key_part[i].fieldnr-1]->null_ptr) + uint fieldnr= key_part[i].fieldnr; + if (!fieldnr || + outparam->field[fieldnr-1]->null_ptr || + outparam->field[fieldnr-1]->key_length() != + key_part[i].length) { primary_key=MAX_KEY; // Can't be used break; @@ -554,6 +557,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; key_part->store_length+=HA_KEY_BLOB_LENGTH; keyinfo->key_length+= HA_KEY_BLOB_LENGTH; + /* + Mark that there may be many matching values for one key + combination ('a', 'a ', 'a '...) + */ + if (!(field->flags & BINARY_FLAG)) + keyinfo->flags|= HA_END_SPACE_KEY; } if (i == 0 && key != primary_key) field->flags |= @@ -591,7 +600,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, } if (field->key_length() != key_part->length) { - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; if (!(field->flags & BLOB_FLAG)) { // Create a new field field=key_part->field=field->new_field(&outparam->mem_root, @@ -605,7 +614,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, as we need to test for NULL = NULL. */ if (field->real_maybe_null()) - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; } else { // Error: shorten key @@ -1237,14 +1246,17 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res) char *get_field(MEM_ROOT *mem, Field *field) { - char buff[MAX_FIELD_WIDTH]; + char buff[MAX_FIELD_WIDTH], *to; String str(buff,sizeof(buff),&my_charset_bin); uint length; field->val_str(&str,&str); - if (!(length= str.length())) + length= str.length(); + if (!length || !(to= (char*) alloc_root(mem,length+1))) return NullS; - return strmake_root(mem, str.ptr(), length); + memcpy(to,str.ptr(),(uint) length); + to[length]=0; + return to; } diff --git a/sql/table.h b/sql/table.h index e492398ed17..ba7349d33fc 100644 --- a/sql/table.h +++ b/sql/table.h @@ -117,7 +117,7 @@ struct st_table { my_bool fulltext_searched; my_bool crashed; my_bool is_view; - my_bool no_keyread; + my_bool no_keyread, no_cache; my_bool clear_query_id; /* To reset query_id for tables and cols */ my_bool auto_increment_field_not_null; Field *next_number_field, /* Set if next_number is activated */ diff --git a/sql/time.cc b/sql/time.cc index fe22b80d59d..9a18a150c50 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -124,6 +124,8 @@ long my_gmt_sec(TIME *t, long *my_timezone) tmp-=t->minute*60 + t->second; // Move to previous hour } *my_timezone= current_timezone; + if (tmp < 0 && t->year <= 1900+YY_PART_YEAR) + tmp= 0; return (long) tmp; } /* my_gmt_sec */ @@ -174,42 +176,72 @@ uint calc_days_in_year(uint year) 366 : 365; } -/* Calculate week. If 'with_year' is not set, then return a week 0-53, where - 0 means that it's the last week of the previous year. - If 'with_year' is set then the week will always be in the range 1-53 and - the year out parameter will contain the year for the week */ -uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week, - uint *year) +/* + The bits in week_format has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. +*/ + +uint calc_week(TIME *l_time, uint week_behaviour, uint *year) { uint days; ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day); ulong first_daynr=calc_daynr(l_time->year,1,1); - uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week); + bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST); + bool week_year= test(week_behaviour & WEEK_YEAR); + bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY); + + uint weekday=calc_weekday(first_daynr, !monday_first); *year=l_time->year; - if (l_time->month == 1 && l_time->day <= 7-weekday && - ((!sunday_first_day_of_week && weekday >= 4) || - (sunday_first_day_of_week && weekday != 0))) + + if (l_time->month == 1 && l_time->day <= 7-weekday) { - /* Last week of the previous year */ - if (!with_year) + if (!week_year && + (first_weekday && weekday != 0 || + !first_weekday && weekday >= 4)) return 0; - with_year=0; // Don't check the week again + week_year= 1; (*year)--; first_daynr-= (days=calc_days_in_year(*year)); weekday= (weekday + 53*7- days) % 7; } - if ((sunday_first_day_of_week && weekday != 0) || - (!sunday_first_day_of_week && weekday >= 4)) + + if ((first_weekday && weekday != 0) || + (!first_weekday && weekday >= 4)) days= daynr - (first_daynr+ (7-weekday)); else days= daynr - (first_daynr - weekday); - if (with_year && days >= 52*7) + + if (week_year && days >= 52*7) { - /* Check if we are on the first week of the next year (or week 53) */ weekday= (weekday + calc_days_in_year(*year)) % 7; - if (weekday < 4) - { // We are at first week on next year + if (!first_weekday && weekday < 4 || + first_weekday && weekday == 0) + { (*year)++; return 1; } @@ -605,7 +637,7 @@ time_t str_to_timestamp(const char *str,uint length) if (str_to_TIME(str,length,&l_time,0) <= TIMESTAMP_DATETIME_ERROR) return(0); - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) { current_thd->cuted_fields++; return(0); diff --git a/sql/uniques.cc b/sql/uniques.cc index 7f8793abc91..a4a5250192d 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -370,7 +370,7 @@ bool Unique::get(TABLE *table) bzero((char*) &sort_param,sizeof(sort_param)); sort_param.max_rows= elements; sort_param.sort_form=table; - sort_param.rec_length= sort_param.sort_length=sort_param.ref_length= + sort_param.rec_length= sort_param.sort_length= sort_param.ref_length= size; sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.not_killable=1; |