diff options
author | unknown <pem@mysql.com> | 2003-12-01 16:14:40 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2003-12-01 16:14:40 +0100 |
commit | 38f853d291075a8eaa9d408a23626b09aa7ac1d2 (patch) | |
tree | 024f2d18e3cf9f65db53f9f8c2d5413859781e16 /sql | |
parent | 6573b851e36de43d4cfa39d5eba0b740c3226521 (diff) | |
parent | 91de6fdbce2a5c545532acf1124f35378a75ea0c (diff) | |
download | mariadb-git-38f853d291075a8eaa9d408a23626b09aa7ac1d2.tar.gz |
Merge 4.1 to 5.0
BitKeeper/etc/ignore:
auto-union
BitKeeper/etc/logging_ok:
auto-union
configure.in:
Auto merged
client/mysql.cc:
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
myisam/mi_check.c:
Auto merged
myisam/myisamchk.c:
Auto merged
myisam/myisamdef.h:
Auto merged
myisam/sort.c:
Auto merged
mysql-test/install_test_db.sh:
Auto merged
mysql-test/r/subselect.result:
Auto merged
mysql-test/r/symlink.result:
Auto merged
mysql-test/t/subselect.test:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_myisam.cc:
Auto merged
sql/handler.cc:
Auto merged
sql/handler.h:
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/log.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/protocol.cc:
Auto merged
sql/protocol.h:
Auto merged
sql/protocol_cursor.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_derived.cc:
Auto merged
sql/sql_error.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_list.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_repl.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_select.h:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_test.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
Diffstat (limited to 'sql')
85 files changed, 1644 insertions, 1075 deletions
diff --git a/sql/derror.cc b/sql/derror.cc index ad7432f7675..53d0dc5b7e5 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -75,6 +75,7 @@ Please install the latest version of this file.",name); goto err1; } + /* TODO: Convert the character set to server system character set */ if (!(cset= get_charset(head[30],MYF(MY_WME)))) { sql_print_error("Character set #%d is not supported for messagefile '%s'", diff --git a/sql/field.cc b/sql/field.cc index befa9993b05..23f6e1232b6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -169,6 +169,128 @@ static inline uint field_length_without_space(const char *ptr, uint length) return (uint) (end-ptr); } +/* + Tables of filed type compatibility. + + There are tables for every type, table consist of list of types in which + given type can be converted without data lost, list should be ended with + FIELD_CAST_STOP +*/ +static Field::field_cast_enum field_cast_decimal[]= +{Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_tiny[]= +{Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, + Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_short[]= +{Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_medium[]= +{Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_long[]= +{Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_longlong[]= +{Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_float[]= +{Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_double[]= +{Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_null[]= +{Field::FIELD_CAST_DECIMAL, Field::FIELD_CAST_TINY, Field::FIELD_CAST_SHORT, + Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_TIMESTAMP, Field::FIELD_CAST_YEAR, + Field::FIELD_CAST_DATE, Field::FIELD_CAST_NEWDATE, + Field::FIELD_CAST_TIME, Field::FIELD_CAST_DATETIME, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, + Field::FIELD_CAST_GEOM, Field::FIELD_CAST_ENUM, Field::FIELD_CAST_SET, + Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_timestamp[]= +{Field::FIELD_CAST_DATETIME, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_year[]= +{Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, + Field::FIELD_CAST_LONGLONG, + Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_date[]= +{Field::FIELD_CAST_DATETIME, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_newdate[]= +{Field::FIELD_CAST_DATETIME, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_time[]= +{Field::FIELD_CAST_DATETIME, + Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_datetime[]= +{Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_string[]= +{Field::FIELD_CAST_VARSTRING, Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_varstring[]= +{Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_blob[]= +{Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_geom[]= +{Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_enum[]= +{Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +static Field::field_cast_enum field_cast_set[]= +{Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, + Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; +// Array of pointers on conversion table for all fields types casting +static Field::field_cast_enum *field_cast_array[]= +{0, //FIELD_CAST_STOP + field_cast_decimal, field_cast_tiny, field_cast_short, + field_cast_medium, field_cast_long, field_cast_longlong, + field_cast_float, field_cast_double, + field_cast_null, + field_cast_timestamp, field_cast_year, field_cast_date, field_cast_newdate, + field_cast_time, field_cast_datetime, + field_cast_string, field_cast_varstring, field_cast_blob, + field_cast_geom, field_cast_enum, field_cast_set +}; + + +bool Field::field_cast_compatible(Field::field_cast_enum type) +{ + DBUG_ASSERT(type != FIELD_CAST_STOP); + Field::field_cast_enum *array= field_cast_array[field_cast_type()]; + uint i= 0; + Field::field_cast_enum tp; + do + { + tp= array[i++]; + if (tp == type) + return 1; + } while (tp != FIELD_CAST_STOP); + return 0; +} + + /**************************************************************************** ** Functions for the base classes ** This is an unpacked number. @@ -2850,7 +2972,7 @@ String *Field_timestamp::val_str(String *val_buffer, struct tm tm_tmp; val_buffer->alloc(field_length+1); - char *to=(char*) val_buffer->ptr(),*end=to+field_length; + char *to= (char*) val_buffer->ptr(); val_buffer->length(field_length); #ifdef WORDS_BIGENDIAN @@ -3635,7 +3757,7 @@ bool Field_newdate::get_date(TIME *ltime,uint fuzzydate) ltime->month= (tmp >> 5) & 15; ltime->year= (tmp >> 9); ltime->time_type=TIMESTAMP_DATE; - ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; + ltime->hour= ltime->minute= ltime->second= ltime->second_part= ltime->neg= 0; return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0; } @@ -3987,7 +4109,6 @@ longlong Field_string::val_int(void) String *Field_string::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { - char *end=ptr+field_length; uint length= field_charset->cset->lengthsp(field_charset, ptr, field_length); val_ptr->set((const char*) ptr, length, field_charset); return val_ptr; diff --git a/sql/field.h b/sql/field.h index 692e64d1146..0b6ba7dde09 100644 --- a/sql/field.h +++ b/sql/field.h @@ -61,6 +61,17 @@ public: GEOM_GEOMETRYCOLLECTION = 7 }; enum imagetype { itRAW, itMBR}; + enum field_cast_enum + { + FIELD_CAST_STOP, FIELD_CAST_DECIMAL, FIELD_CAST_TINY, FIELD_CAST_SHORT, + FIELD_CAST_MEDIUM, FIELD_CAST_LONG, FIELD_CAST_LONGLONG, + FIELD_CAST_FLOAT, FIELD_CAST_DOUBLE, + FIELD_CAST_NULL, + FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE, + FIELD_CAST_TIME, FIELD_CAST_DATETIME, + FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB, + FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET + }; utype unireg_check; uint32 field_length; // Length of field @@ -230,6 +241,8 @@ public: virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } void set_warning(const unsigned int level, const unsigned int code); + virtual field_cast_enum field_cast_type()= 0; + bool field_cast_compatible(field_cast_enum type); friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options, ulonglong auto_increment_value); @@ -334,6 +347,7 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_DECIMAL; } }; @@ -369,6 +383,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 1; } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_TINY; } }; @@ -404,6 +419,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 2; } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_SHORT; } }; @@ -434,6 +450,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_MEDIUM; } }; @@ -469,6 +486,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_LONG; } }; @@ -507,6 +525,7 @@ public: uint32 pack_length() const { return 8; } void sql_type(String &str) const; bool store_for_compare() { return 1; } + field_cast_enum field_cast_type() { return FIELD_CAST_LONGLONG; } }; #endif @@ -540,6 +559,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_FLOAT; } }; @@ -573,6 +593,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_DOUBLE; } }; @@ -606,6 +627,7 @@ public: uint32 pack_length() const { return 0; } void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } + field_cast_enum field_cast_type() { return FIELD_CAST_NULL; } }; @@ -649,6 +671,7 @@ public: } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + field_cast_enum field_cast_type() { return FIELD_CAST_TIMESTAMP; } }; @@ -674,6 +697,7 @@ public: String *val_str(String*,String *); bool send_binary(Protocol *protocol); void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_YEAR; } }; @@ -706,6 +730,7 @@ public: void sql_type(String &str) const; bool store_for_compare() { return 1; } bool zero_pack() const { return 1; } + field_cast_enum field_cast_type() { return FIELD_CAST_DATE; } }; class Field_newdate :public Field_str { @@ -737,6 +762,7 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + field_cast_enum field_cast_type() { return FIELD_CAST_NEWDATE; } }; @@ -770,6 +796,7 @@ public: void sql_type(String &str) const; bool store_for_compare() { return 1; } bool zero_pack() const { return 1; } + field_cast_enum field_cast_type() { return FIELD_CAST_TIME; } }; @@ -807,6 +834,7 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + field_cast_enum field_cast_type() { return FIELD_CAST_DATETIME; } }; @@ -851,6 +879,7 @@ public: uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_STRING; } bool has_charset(void) const { return TRUE; } + field_cast_enum field_cast_type() { return FIELD_CAST_STRING; } }; @@ -894,6 +923,7 @@ public: uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } bool has_charset(void) const { return TRUE; } + field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; } }; @@ -911,7 +941,7 @@ public: 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), - geom_flag(true), packlength(3) + geom_flag(true), packlength(4) { flags|= BLOB_FLAG; } @@ -983,6 +1013,7 @@ public: uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } + field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; } }; @@ -1011,6 +1042,7 @@ public: void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); void set_key_image(char *buff,uint length, CHARSET_INFO *cs); + field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; } }; @@ -1052,6 +1084,7 @@ public: bool optimize_range(uint idx) { return 0; } bool eq_def(Field *field); bool has_charset(void) const { return TRUE; } + field_cast_enum field_cast_type() { return FIELD_CAST_ENUM; } }; @@ -1077,6 +1110,7 @@ public: void sql_type(String &str) const; enum_field_types real_type() const { return FIELD_TYPE_SET; } bool has_charset(void) const { return TRUE; } + field_cast_enum field_cast_type() { return FIELD_CAST_SET; } }; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index fb4061b31e0..ae0267b98f3 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -248,7 +248,8 @@ ha_rows ha_heap::records_in_range(int inx, } } -int ha_heap::create(const char *name, TABLE *table, + +int ha_heap::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { uint key, parts, mem_per_row= 0; @@ -259,17 +260,17 @@ int ha_heap::create(const char *name, TABLE *table, char buff[FN_REFLEN]; int error; - for (key= parts= 0; key < table->keys; key++) - parts+= table->key_info[key].key_parts; + for (key= parts= 0; key < table_arg->keys; key++) + parts+= table_arg->key_info[key].key_parts; - if (!(keydef= (HP_KEYDEF*) my_malloc(table->keys * sizeof(HP_KEYDEF) + + if (!(keydef= (HP_KEYDEF*) my_malloc(table_arg->keys * sizeof(HP_KEYDEF) + parts * sizeof(HA_KEYSEG), MYF(MY_WME)))) return my_errno; - seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + table->keys); - for (key= 0; key < table->keys; key++) + seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + table_arg->keys); + for (key= 0; key < table_arg->keys; key++) { - KEY *pos= table->key_info+key; + KEY *pos= table_arg->key_info+key; KEY_PART_INFO *key_part= pos->key_part; KEY_PART_INFO *key_part_end= key_part + pos->key_parts; @@ -303,7 +304,7 @@ int ha_heap::create(const char *name, TABLE *table, if (field->null_ptr) { seg->null_bit= field->null_bit; - seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]); + seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]); } else { @@ -317,7 +318,7 @@ int ha_heap::create(const char *name, TABLE *table, } } } - mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*)); + mem_per_row+= MY_ALIGN(table_arg->reclength + 1, sizeof(char*)); max_rows = (ha_rows) (current_thd->variables.max_heap_table_size / mem_per_row); HP_CREATE_INFO hp_create_info; @@ -326,10 +327,11 @@ int ha_heap::create(const char *name, TABLE *table, hp_create_info.auto_increment= (create_info->auto_increment_value ? create_info->auto_increment_value - 1 : 0); error= heap_create(fn_format(buff,name,"","",4+2), - table->keys,keydef, table->reclength, - (ulong) ((table->max_rows < max_rows && table->max_rows) ? - table->max_rows : max_rows), - (ulong) table->min_rows, &hp_create_info); + table_arg->keys,keydef, table_arg->reclength, + (ulong) ((table_arg->max_rows < max_rows && + table_arg->max_rows) ? + table_arg->max_rows : max_rows), + (ulong) table_arg->min_rows, &hp_create_info); my_free((gptr) keydef, MYF(0)); if (file) info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); @@ -337,6 +339,7 @@ int ha_heap::create(const char *name, TABLE *table, return (error); } + void ha_heap::update_create_info(HA_CREATE_INFO *create_info) { table->file->info(HA_STATUS_AUTO); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c10eec73274..cbbb0d96d22 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -46,6 +46,7 @@ InnoDB */ #include "ha_innodb.h" pthread_mutex_t innobase_mutex; +bool innodb_inited= 0; /* Store MySQL definition of 'byte': in Linux it is char while InnoDB uses unsigned char; the header univ.i which we include next defines @@ -75,6 +76,7 @@ extern "C" { #include "../innobase/include/btr0cur.h" #include "../innobase/include/btr0btr.h" #include "../innobase/include/fsp0fsp.h" +#include "../innobase/include/fil0fil.h" } #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */ @@ -546,7 +548,6 @@ innobase_query_caching_of_table_permitted( { ibool is_autocommit; trx_t* trx; - char* ptr; char norm_name[1000]; ut_a(full_name_len < 999); @@ -606,7 +607,7 @@ innobase_query_caching_of_table_permitted( #ifdef __WIN__ /* Put to lower case */ - ptr = norm_name; + char* ptr = norm_name; while (*ptr != '\0') { *ptr = tolower(*ptr); @@ -739,6 +740,7 @@ innobase_init(void) if (mysql_embedded) { default_path = mysql_real_data_home; + fil_path_to_mysql_datadir = mysql_real_data_home; } else { /* It's better to use current lib, to keep paths short */ current_dir[0] = FN_CURLIB; @@ -899,6 +901,7 @@ innobase_init(void) (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0, (hash_get_key) innobase_get_key, 0, 0); pthread_mutex_init(&innobase_mutex, MY_MUTEX_INIT_FAST); + innodb_inited= 1; /* If this is a replication slave and we needed to do a crash recovery, set the master binlog position to what InnoDB internally knew about @@ -926,21 +929,21 @@ innobase_end(void) /*==============*/ /* out: TRUE if error */ { - int err; + int err= 0; DBUG_ENTER("innobase_end"); - err = innobase_shutdown_for_mysql(); - hash_free(&innobase_open_tables); - my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR)); - pthread_mutex_destroy(&innobase_mutex); - - if (err != DB_SUCCESS) { - - DBUG_RETURN(1); + if (innodb_inited) + { + innodb_inited= 0; + if (innobase_shutdown_for_mysql() != DB_SUCCESS) + err= 1; + hash_free(&innobase_open_tables); + my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR)); + pthread_mutex_destroy(&innobase_mutex); } - DBUG_RETURN(0); + DBUG_RETURN(err); } /******************************************************************** @@ -1391,7 +1394,6 @@ ha_innobase::open( uint test_if_locked) /* in: not used */ { dict_table_t* ib_table; - int error = 0; char norm_name[1000]; DBUG_ENTER("ha_innobase::open"); @@ -1534,7 +1536,7 @@ ha_innobase::open( fprintf(stderr, "InnoDB: Warning: table %s key_used_on_scan is %lu even though there is no\n" "InnoDB: primary key inside InnoDB.\n", - name, (ulint)key_used_on_scan); + name, (ulong)key_used_on_scan); } } @@ -3214,7 +3216,7 @@ ha_innobase::position( if (len != ref_length) { fprintf(stderr, "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n", - (ulint)len, (ulint)ref_length); + (ulong)len, (ulong)ref_length); } } @@ -3638,7 +3640,7 @@ ha_innobase::discard_or_import_tablespace( my_bool discard) /* in: TRUE if discard, else import */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - dict_table_t* table; + dict_table_t* dict_table; trx_t* trx; int err; @@ -3648,13 +3650,13 @@ ha_innobase::discard_or_import_tablespace( ut_a(prebuilt->trx == (trx_t*) current_thd->transaction.all.innobase_tid); - table = prebuilt->table; + dict_table = prebuilt->table; trx = prebuilt->trx; if (discard) { - err = row_discard_tablespace_for_mysql(table->name, trx); + err = row_discard_tablespace_for_mysql(dict_table->name, trx); } else { - err = row_import_tablespace_for_mysql(table->name, trx); + err = row_import_tablespace_for_mysql(dict_table->name, trx); } if (err == DB_SUCCESS) { @@ -4185,7 +4187,8 @@ ha_innobase::info( "InnoDB: .frm files from different installations? See section\n" "InnoDB: 15.1 at http://www.innodb.com/ibman.html\n", index->name, - ib_table->name, index->n_uniq, + ib_table->name, + (unsigned long) index->n_uniq, j + 1); break; } diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc index 94e394e7665..9915c182e26 100644 --- a/sql/ha_isammrg.cc +++ b/sql/ha_isammrg.cc @@ -157,7 +157,7 @@ void ha_isammrg::info(uint flag) deleted = (ha_rows) info.deleted; data_file_length=info.data_file_length; errkey = info.errkey; - table->keys_in_use=0; // No keys yet + table->keys_in_use.clear_all(); // No keys yet table->db_options_in_use = info.options; mean_rec_length=info.reclength; block_size=0; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 09f034b27bf..6356f209ba2 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -226,7 +226,6 @@ err: int ha_myisam::open(const char *name, int mode, uint test_if_locked) { - KEY_CACHE_VAR *key_cache; if (!(file=mi_open(name, mode, test_if_locked))) return (my_errno ? my_errno : -1); @@ -698,7 +697,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) { - KEY_CACHE_VAR *new_key_cache= check_opt->key_cache; + KEY_CACHE *new_key_cache= check_opt->key_cache; const char *errmsg= 0; int error= HA_ADMIN_OK; ulonglong map= ~(ulonglong) 0; @@ -721,13 +720,10 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) if ((error= mi_assign_to_key_cache(file, map, new_key_cache))) { - switch (error) { - default: - char buf[80]; - my_snprintf(buf, sizeof(buf), - "Failed to flush to index file (errno: %d)", error); - errmsg= buf; - } + char buf[80]; + my_snprintf(buf, sizeof(buf), + "Failed to flush to index file (errno: %d)", error); + errmsg= buf; error= HA_ADMIN_CORRUPT; } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index a834ace7032..3cd5d96d5f3 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -39,7 +39,6 @@ const char **ha_myisammrg::bas_ext() const int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) { char name_buff[FN_REFLEN]; - KEY_CACHE_VAR *key_cache; DBUG_PRINT("info", ("ha_myisammrg::open")); if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode, @@ -312,11 +311,11 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, static void split_file_name(const char *file_name, LEX_STRING *db, LEX_STRING *name) { - uint name_length, dir_length, prefix_length; + uint dir_length, prefix_length; char buff[FN_REFLEN]; db->length= 0; - name_length= (uint) (strmake(buff, file_name, sizeof(buff)-1) - buff); + strmake(buff, file_name, sizeof(buff)-1); dir_length= dirname_length(buff); if (dir_length > 1) { diff --git a/sql/handler.cc b/sql/handler.cc index 96444f97da8..ac14f383eab 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1171,20 +1171,22 @@ void st_ha_check_opt::init() /* Init a key cache if it has not been initied before */ -int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache) +int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) { DBUG_ENTER("ha_init_key_cache"); - if (!key_cache->cache) + if (!key_cache->key_cache_inited) { pthread_mutex_lock(&LOCK_global_system_variables); - long tmp_buff_size= (long) key_cache->buff_size; - long tmp_block_size= (long) key_cache->block_size; + long tmp_buff_size= (long) key_cache->param_buff_size; + long tmp_block_size= (long) key_cache->param_block_size; + uint division_limit= key_cache->param_division_limit; + uint age_threshold= key_cache->param_age_threshold; pthread_mutex_unlock(&LOCK_global_system_variables); - DBUG_RETURN(!init_key_cache(&key_cache->cache, + DBUG_RETURN(!init_key_cache(key_cache, tmp_block_size, tmp_buff_size, - key_cache)); + division_limit, age_threshold)); } DBUG_RETURN(0); } @@ -1192,18 +1194,21 @@ int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache) /* Resize key cache */ -int ha_resize_key_cache(KEY_CACHE_VAR *key_cache) +int ha_resize_key_cache(KEY_CACHE *key_cache) { DBUG_ENTER("ha_resize_key_cache"); - if (key_cache->cache) + if (key_cache->key_cache_inited) { pthread_mutex_lock(&LOCK_global_system_variables); - long tmp_buff_size= (long) key_cache->buff_size; - long tmp_block_size= (long) key_cache->block_size; + long tmp_buff_size= (long) key_cache->param_buff_size; + long tmp_block_size= (long) key_cache->param_block_size; + uint division_limit= key_cache->param_division_limit; + uint age_threshold= key_cache->param_age_threshold; pthread_mutex_unlock(&LOCK_global_system_variables); - DBUG_RETURN(!resize_key_cache(&key_cache->cache, tmp_block_size, - tmp_buff_size)); + DBUG_RETURN(!resize_key_cache(key_cache, tmp_block_size, + tmp_buff_size, + division_limit, age_threshold)); } DBUG_RETURN(0); } @@ -1211,29 +1216,31 @@ int ha_resize_key_cache(KEY_CACHE_VAR *key_cache) /* Change parameters for key cache (like size) */ -int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache) +int ha_change_key_cache_param(KEY_CACHE *key_cache) { - if (key_cache->cache) - change_key_cache_param(key_cache->cache); + if (key_cache->key_cache_inited) + { + pthread_mutex_lock(&LOCK_global_system_variables); + uint division_limit= key_cache->param_division_limit; + uint age_threshold= key_cache->param_age_threshold; + pthread_mutex_unlock(&LOCK_global_system_variables); + change_key_cache_param(key_cache, division_limit, age_threshold); + } return 0; } /* Free memory allocated by a key cache */ -int ha_end_key_cache(KEY_CACHE_VAR *key_cache) +int ha_end_key_cache(KEY_CACHE *key_cache) { - if (key_cache->cache) - { - end_key_cache(key_cache->cache, 1); // Can never fail - key_cache->cache= 0; - } + end_key_cache(key_cache, 1); // Can never fail return 0; } /* Move all tables from one key cache to another one */ -int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache, - KEY_CACHE_VAR *new_key_cache) +int ha_change_key_cache(KEY_CACHE *old_key_cache, + KEY_CACHE *new_key_cache) { mi_change_key_cache(old_key_cache, new_key_cache); return 0; diff --git a/sql/handler.h b/sql/handler.h index f4ae45fafe3..49c7e9d06c5 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -22,6 +22,7 @@ #endif #include <ft_global.h> +#include <keycache.h> #ifndef NO_HASH #define NO_HASH /* Not yet implemented */ @@ -181,14 +182,13 @@ typedef struct st_ha_create_information struct st_table; typedef struct st_table TABLE; -typedef struct st_key_cache_asmt KEY_CACHE_ASMT; typedef struct st_ha_check_opt { ulong sort_buffer_size; uint flags; /* isam layer flags (e.g. for myisamchk) */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ - KEY_CACHE_VAR *key_cache; /* new key cache when changing key cache */ + KEY_CACHE *key_cache; /* new key cache when changing key cache */ void init(); } HA_CHECK_OPT; @@ -395,10 +395,10 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, bool update_create_info); int ha_delete_table(enum db_type db_type, const char *path); void ha_drop_database(char* path); -int ha_init_key_cache(const char *name, KEY_CACHE_VAR *key_cache); -int ha_resize_key_cache(KEY_CACHE_VAR *key_cache); -int ha_change_key_cache_param(KEY_CACHE_VAR *key_cache); -int ha_end_key_cache(KEY_CACHE_VAR *key_cache); +int ha_init_key_cache(const char *name, KEY_CACHE *key_cache); +int ha_resize_key_cache(KEY_CACHE *key_cache); +int ha_change_key_cache_param(KEY_CACHE *key_cache); +int ha_end_key_cache(KEY_CACHE *key_cache); int ha_start_stmt(THD *thd); int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name, my_off_t end_offset); @@ -412,5 +412,5 @@ int ha_autocommit_or_rollback(THD *thd, int error); void ha_set_spin_retries(uint retries); bool ha_flush_logs(void); int ha_recovery_logging(THD *thd, bool on); -int ha_change_key_cache(KEY_CACHE_VAR *old_key_cache, - KEY_CACHE_VAR *new_key_cache); +int ha_change_key_cache(KEY_CACHE *old_key_cache, + KEY_CACHE *new_key_cache); diff --git a/sql/hostname.cc b/sql/hostname.cc index 5c4bde99256..c9cb2a43963 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -61,23 +61,27 @@ bool hostname_cache_init() { host_entry tmp; uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp); - (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); - if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, sizeof(struct in_addr),NULL, (hash_free_key) free, &my_charset_latin1))) return 1; hostname_cache->clear(); + (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); return 0; } void hostname_cache_free() { - (void) pthread_mutex_destroy(&LOCK_hostname); - delete hostname_cache; + if (hostname_cache) + { + (void) pthread_mutex_destroy(&LOCK_hostname); + delete hostname_cache; + hostname_cache= 0; + } } + static void add_hostname(struct in_addr *in,const char *name) { if (!(specialflag & SPECIAL_NO_HOST_CACHE)) diff --git a/sql/item.cc b/sql/item.cc index 0c5b6450b4a..f67599b8d95 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -331,7 +331,7 @@ void Item_field::set_field(Field *field_par) const char *Item_ident::full_name() const { char *tmp; - if (!table_name) + if (!table_name || !field_name) return field_name ? field_name : name ? name : "tmp_field"; if (db_name && db_name[0]) { @@ -531,7 +531,7 @@ String *Item_null::val_str(String *str) void Item_param::set_null() { DBUG_ENTER("Item_param::set_null"); - maybe_null= null_value= 1; + maybe_null= null_value= value_is_set= 1; DBUG_VOID_RETURN; } @@ -540,6 +540,7 @@ void Item_param::set_int(longlong i) DBUG_ENTER("Item_param::set_int"); int_value= (longlong)i; item_type= INT_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("integer: %lld", int_value)); DBUG_VOID_RETURN; } @@ -549,6 +550,7 @@ void Item_param::set_double(double value) DBUG_ENTER("Item_param::set_double"); real_value=value; item_type= REAL_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("double: %lg", real_value)); DBUG_VOID_RETURN; } @@ -559,6 +561,7 @@ void Item_param::set_value(const char *str, uint length) DBUG_ENTER("Item_param::set_value"); str_value.copy(str,length,default_charset()); item_type= STRING_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("string: %s", str_value.ptr())); DBUG_VOID_RETURN; } @@ -580,6 +583,7 @@ void Item_param::set_time(TIME *tm, timestamp_type type) item_is_time= true; item_type= STRING_ITEM; + value_is_set= 1; } @@ -587,6 +591,7 @@ void Item_param::set_longdata(const char *str, ulong length) { str_value.append(str,length); long_data_supplied= 1; + value_is_set= 1; } @@ -1209,6 +1214,15 @@ int Item_string::save_in_field(Field *field, bool no_conversions) -1 : 0; } +int Item_uint::save_in_field(Field *field, bool no_conversions) +{ + /* + TODO: To be fixed when wen have a + field->store(longlong, unsigned_flag) method + */ + return Item_int::save_in_field(field, no_conversions); +} + int Item_int::save_in_field(Field *field, bool no_conversions) { @@ -1366,7 +1380,7 @@ bool Item::send(Protocol *protocol, String *buffer) case MYSQL_TYPE_FLOAT: { float nr; - nr= val(); + nr= (float) val(); if (!null_value) result= protocol->store(nr, decimals, buffer); break; @@ -1672,7 +1686,9 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const } -bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) +bool Item_insert_value::fix_fields(THD *thd, + struct st_table_list *table_list, + Item **items) { bool res= arg->fix_fields(thd, table_list, items); if (res) @@ -1703,10 +1719,10 @@ bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, I } else { - Field *field=field_arg->field; + Field *tmp_field= field_arg->field; /* charset doesn't matter here, it's to avoid sigsegv only */ - set_field(new Field_null(0,0,Field::NONE,field->field_name,field->table, - &my_charset_bin)); + set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name, + tmp_field->table, &my_charset_bin)); } return 0; } @@ -1886,6 +1902,8 @@ void Item_cache_str::store(Item *item) } collation.set(item->collation); } + + double Item_cache_str::val() { int err; @@ -1895,6 +1913,8 @@ double Item_cache_str::val() else return (double)0; } + + longlong Item_cache_str::val_int() { int err; @@ -1905,6 +1925,7 @@ longlong Item_cache_str::val_int() return (longlong)0; } + bool Item_cache_row::allocate(uint num) { item_count= num; @@ -1913,6 +1934,7 @@ bool Item_cache_row::allocate(uint num) (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count))); } + bool Item_cache_row::setup(Item * item) { example= item; @@ -1929,6 +1951,7 @@ bool Item_cache_row::setup(Item * item) return 0; } + void Item_cache_row::store(Item * item) { null_value= 0; @@ -1940,6 +1963,7 @@ void Item_cache_row::store(Item * item) } } + void Item_cache_row::illegal_method_call(const char *method) { DBUG_ENTER("Item_cache_row::illegal_method_call"); @@ -1949,6 +1973,7 @@ void Item_cache_row::illegal_method_call(const char *method) DBUG_VOID_RETURN; } + bool Item_cache_row::check_cols(uint c) { if (c != item_count) @@ -1959,6 +1984,7 @@ bool Item_cache_row::check_cols(uint c) return 0; } + bool Item_cache_row::null_inside() { for (uint i= 0; i < item_count; i++) @@ -1978,6 +2004,7 @@ bool Item_cache_row::null_inside() return 0; } + void Item_cache_row::bring_value() { for (uint i= 0; i < item_count; i++) @@ -1985,6 +2012,132 @@ void Item_cache_row::bring_value() return; } + +Item_type_holder::Item_type_holder(THD *thd, Item *item) + :Item(thd, *item), item_type(item->result_type()) +{ + DBUG_ASSERT(item->fixed); + + /* + It is safe assign pointer on field, because it will be used just after + all JOIN::prepare calls and before any SELECT execution + */ + if (item->type() == Item::FIELD_ITEM) + field_example= ((Item_field*) item)->field; + else + field_example= 0; + collation.set(item->collation); +} + + +/* + STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT + + ROW_RESULT should never appear in Item_type_holder::join_types, + but it is included in following table just to make table full + (there DBUG_ASSERT in function to catch ROW_RESULT) +*/ +static Item_result type_convertor[4][4]= +{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}, + {ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}}; + +bool Item_type_holder::join_types(THD *thd, Item *item) +{ + bool change_field= 0, skip_store_field= 0; + Item_result new_type= type_convertor[item_type][item->result_type()]; + + // we have both fields + if (field_example && item->type() == Item::FIELD_ITEM) + { + Field *field= ((Item_field *)item)->field; + if (field_example->field_cast_type() != field->field_cast_type()) + { + if (!(change_field= + field_example->field_cast_compatible(field->field_cast_type()))) + { + /* + if old field can't store value of 'worse' new field we will make + decision about result field type based only on Item result type + */ + if (!field->field_cast_compatible(field_example->field_cast_type())) + skip_store_field= 1; + } + } + } + + // size/type should be changed + if (change_field || + (new_type != item_type) || + (max_length < item->max_length) || + ((new_type == INT_RESULT) && + (decimals < item->decimals)) || + (!maybe_null && item->maybe_null) || + (item_type == STRING_RESULT && new_type == STRING_RESULT && + !my_charset_same(collation.collation, item->collation.collation))) + { + // new field has some parameters worse then current + skip_store_field|= (change_field && + (max_length > item->max_length) || + ((new_type == INT_RESULT) && + (decimals > item->decimals)) || + (maybe_null && !item->maybe_null) || + (item_type == STRING_RESULT && + new_type == STRING_RESULT && + !my_charset_same(collation.collation, + item->collation.collation))); + /* + It is safe assign pointer on field, because it will be used just after + all JOIN::prepare calls and before any SELECT execution + */ + if (skip_store_field || item->type() != Item::FIELD_ITEM) + field_example= 0; + else + field_example= ((Item_field*) item)->field; + + const char *old_cs= collation.collation->name, + *old_derivation= collation.derivation_name(); + if (item_type == STRING_RESULT && collation.aggregate(item->collation)) + { + my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), + old_cs, old_derivation, + item->collation.collation->name, + item->collation.derivation_name(), + "UNION"); + return 1; + } + + max_length= max(max_length, item->max_length); + decimals= max(decimals, item->decimals); + maybe_null|= item->maybe_null; + item_type= new_type; + } + DBUG_ASSERT(item_type != ROW_RESULT); + return 0; +} + + +double Item_type_holder::val() +{ + DBUG_ASSERT(0); // should never be called + return 0.0; +} + + +longlong Item_type_holder::val_int() +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + + +String *Item_type_holder::val_str(String*) +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index 13b729095d8..a7742f41b56 100644 --- a/sql/item.h +++ b/sql/item.h @@ -98,7 +98,7 @@ public: COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, - SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; + SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; @@ -174,7 +174,17 @@ public: virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} + /* + Returns true if this is constant (during query execution, i.e. its value + will not change until next fix_fields) and its value is known. + */ virtual bool const_item() const { return used_tables() == 0; } + /* + Returns true if this is constant but its value may be not known yet. + (Can be used for parameters of prep. stmts or of stored procedures.) + */ + virtual bool const_during_execution() const + { return (used_tables() & ~PARAM_TABLE_BIT) == 0; } virtual void print(String *str_arg) { str_arg->append(full_name()); } void print_item_w_name(String *); virtual void update_used_tables() {} @@ -412,6 +422,7 @@ public: class Item_param :public Item { public: + bool value_is_set; longlong int_value; double real_value; TIME ltime; @@ -430,6 +441,7 @@ public: item_result_type = STRING_RESULT; item_is_time= false; long_data_supplied= false; + value_is_set= 0; } enum Type type() const { return item_type; } double val(); @@ -457,6 +469,13 @@ public: String *query_val_str(String *str); enum_field_types field_type() const { return MYSQL_TYPE_STRING; } Item *new_item() { return new Item_param(pos_in_query); } + /* + If value for parameter was not set we treat it as non-const + so noone will use parameters value in fix_fields still + parameter is constant during execution. + */ + virtual table_map used_tables() const + { return value_is_set ? (table_map)0 : PARAM_TABLE_BIT; } void print(String *str) { str->append('?'); } }; @@ -465,17 +484,17 @@ class Item_int :public Item public: const longlong value; Item_int(int32 i,uint length=11) :value((longlong) i) - { max_length=length;} + { max_length=length; fixed= 1; } #ifdef HAVE_LONG_LONG Item_int(longlong i,uint length=21) :value(i) - { max_length=length;} + { max_length=length; fixed= 1;} #endif Item_int(const char *str_arg,longlong i,uint length) :value(i) - { max_length=length; name=(char*) str_arg;} + { max_length=length; name=(char*) str_arg; fixed= 1; } Item_int(const char *str_arg) : value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) : (longlong) strtoull(str_arg,(char**) 0,10)) - { max_length= (uint) strlen(str_arg); name=(char*) str_arg;} + { max_length= (uint) strlen(str_arg); name=(char*) str_arg; fixed= 1; } enum Type type() const { return INT_ITEM; } enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } @@ -498,6 +517,7 @@ public: double val() { return ulonglong2double((ulonglong)value); } String *val_str(String*); Item *new_item() { return new Item_uint(name,max_length); } + int save_in_field(Field *field, bool no_conversions); bool fix_fields(THD *thd, struct st_table_list *list, Item **item) { bool res= Item::fix_fields(thd, list, item); @@ -904,14 +924,14 @@ public: bool fix_fields(THD *, struct st_table_list *, Item **); void print(String *str); virtual bool basic_const_item() const { return true; } - int save_in_field(Field *field, bool no_conversions) + int save_in_field(Field *field_arg, bool no_conversions) { if (!arg) { - field->set_default(); + field_arg->set_default(); return 0; } - return Item_field::save_in_field(field, no_conversions); + return Item_field::save_in_field(field_arg, no_conversions); } table_map used_tables() const { return (table_map)0L; } @@ -932,9 +952,9 @@ public: bool fix_fields(THD *, struct st_table_list *, Item **); void print(String *str); virtual bool basic_const_item() const { return true; } - int save_in_field(Field *field, bool no_conversions) + int save_in_field(Field *field_arg, bool no_conversions) { - return Item_field::save_in_field(field, no_conversions); + return Item_field::save_in_field(field_arg, no_conversions); } table_map used_tables() const { return (table_map)0L; } @@ -1062,6 +1082,28 @@ public: void bring_value(); }; + +/* + Used to store type. name, length of Item for UNIONS & derived table +*/ +class Item_type_holder: public Item +{ +protected: + Item_result item_type; + Field *field_example; +public: + Item_type_holder(THD*, Item*); + + Item_result result_type () const { return item_type; } + enum Type type() const { return TYPE_HOLDER; } + double val(); + longlong val_int(); + String *val_str(String*); + bool join_types(THD *thd, Item *); + Field *example() { return field_example; } +}; + + extern Item_buff *new_Item_buff(Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item *resolve_const_item(Item *item,Item *cmp_item); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1629ed6aa80..8a8438d5aa3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -397,13 +397,12 @@ int Arg_comparator::compare_row() int Arg_comparator::compare_e_row() { - int res= 0; (*a)->bring_value(); (*b)->bring_value(); uint n= (*a)->cols(); for (uint i= 0; i<n; i++) { - if ((res= !comparators[i].compare())) + if (!comparators[i].compare()) return 0; } return 1; @@ -1096,8 +1095,10 @@ void Item_func_case::fix_length_and_dec() return; - // Aggregate first expression and all THEN expression types - // and collations when string comparison + /* + Aggregate first expression and all THEN expression types + and collations when string comparison + */ if (first_expr_num != -1) { agg[0]= args[first_expr_num]; @@ -1110,7 +1111,7 @@ void Item_func_case::fix_length_and_dec() return; } - if (!else_expr_num != -1 || args[else_expr_num]->maybe_null) + if (else_expr_num == -1 || args[else_expr_num]->maybe_null) maybe_null=1; max_length=0; @@ -1127,6 +1128,7 @@ void Item_func_case::fix_length_and_dec() } } + /* TODO: Fix this so that it prints the whole CASE expression */ void Item_func_case::print(String *str) @@ -1375,6 +1377,7 @@ cmp_item* cmp_item::get_comparator(Item *item) return 0; // to satisfy compiler :) } + cmp_item* cmp_item_sort_string::make_same() { return new cmp_item_sort_string_in_static(cmp_charset); @@ -1395,27 +1398,46 @@ cmp_item* cmp_item_row::make_same() return new cmp_item_row(); } + +cmp_item_row::~cmp_item_row() +{ + DBUG_ENTER("~cmp_item_row"); + DBUG_PRINT("enter",("this: %lx", this)); + if (comparators) + { + for (uint i= 0; i < n; i++) + { + if (comparators[i]) + delete comparators[i]; + } + } + DBUG_VOID_RETURN; +} + + void cmp_item_row::store_value(Item *item) { - THD *thd= current_thd; + DBUG_ENTER("cmp_item_row::store_value"); n= item->cols(); - if ((comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *)*n))) + if (!comparators) + comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n); + if (comparators) { item->bring_value(); item->null_value= 0; for (uint i=0; i < n; i++) - if ((comparators[i]= cmp_item::get_comparator(item->el(i)))) - { - comparators[i]->store_value(item->el(i)); - item->null_value|= item->el(i)->null_value; - } - else - return; + { + if (!comparators[i]) + if (!(comparators[i]= cmp_item::get_comparator(item->el(i)))) + break; // new failed + comparators[i]->store_value(item->el(i)); + item->null_value|= item->el(i)->null_value; + } } - else - return; + DBUG_VOID_RETURN; } + void cmp_item_row::store_value_by_template(cmp_item *t, Item *item) { cmp_item_row *tmpl= (cmp_item_row*) t; @@ -1430,19 +1452,17 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item) item->bring_value(); item->null_value= 0; for (uint i=0; i < n; i++) - if ((comparators[i]= tmpl->comparators[i]->make_same())) - { - comparators[i]->store_value_by_template(tmpl->comparators[i], - item->el(i)); - item->null_value|= item->el(i)->null_value; - } - else - return; + { + if (!(comparators[i]= tmpl->comparators[i]->make_same())) + break; // new failed + comparators[i]->store_value_by_template(tmpl->comparators[i], + item->el(i)); + item->null_value|= item->el(i)->null_value; + } } - else - return; } + int cmp_item_row::cmp(Item *arg) { arg->null_value= 0; @@ -1454,25 +1474,31 @@ int cmp_item_row::cmp(Item *arg) bool was_null= 0; arg->bring_value(); for (uint i=0; i < n; i++) + { if (comparators[i]->cmp(arg->el(i))) { if (!arg->el(i)->null_value) return 1; was_null= 1; } + } return (arg->null_value= was_null); } + int cmp_item_row::compare(cmp_item *c) { - int res; cmp_item_row *cmp= (cmp_item_row *) c; for (uint i=0; i < n; i++) + { + int res; if ((res= comparators[i]->compare(cmp->comparators[i]))) return res; + } return 0; } + bool Item_func_in::nulls_in_row() { Item **arg,**arg_end; @@ -1484,6 +1510,7 @@ bool Item_func_in::nulls_in_row() return 0; } + static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) { return cs->coll->strnncollsp(cs, @@ -1491,6 +1518,7 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) (unsigned char *) y->ptr(),y->length()); } + void Item_func_in::fix_length_and_dec() { Item **arg, **arg_end; @@ -1512,7 +1540,6 @@ void Item_func_in::fix_length_and_dec() { switch (cmp_type) { case STRING_RESULT: - uint i; array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in, cmp_collation.collation); break; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index dac7a2d43eb..dc017cef73c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -41,24 +41,24 @@ public: Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {}; int set_compare_func(Item_bool_func2 *owner, Item_result type); - inline int set_compare_func(Item_bool_func2 *owner) + inline int set_compare_func(Item_bool_func2 *owner_arg) { - return set_compare_func(owner, item_cmp_type((*a)->result_type(), - (*b)->result_type())); + return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(), + (*b)->result_type())); } - inline int set_cmp_func(Item_bool_func2 *owner, + inline int set_cmp_func(Item_bool_func2 *owner_arg, Item **a1, Item **a2, Item_result type) { a= a1; b= a2; - return set_compare_func(owner, type); + return set_compare_func(owner_arg, type); } - inline int set_cmp_func(Item_bool_func2 *owner, + inline int set_cmp_func(Item_bool_func2 *owner_arg, Item **a1, Item **a2) { - return set_cmp_func(owner, a1, a2, item_cmp_type((*a1)->result_type(), - (*a2)->result_type())); + return set_cmp_func(owner_arg, a1, a2, item_cmp_type((*a1)->result_type(), + (*a2)->result_type())); } inline int compare() { return (this->*func)(); } @@ -638,17 +638,7 @@ class cmp_item_row :public cmp_item uint n; public: cmp_item_row(): comparators(0), n(0) {} - ~cmp_item_row() - { - if (comparators) - { - for (uint i= 0; i < n; i++) - { - if (comparators[i]) - delete comparators[i]; - } - } - } + ~cmp_item_row(); void store_value(Item *item); int cmp(Item *arg); int compare(cmp_item *arg); @@ -694,7 +684,7 @@ public: cmp_item_string *cmp= (cmp_item_string *)c; return sortcmp(value_res, cmp->value_res, cmp_charset); } - cmp_item * make_same() + cmp_item *make_same() { return new cmp_item_sort_string_in_static(cmp_charset); } @@ -715,7 +705,10 @@ class Item_func_in :public Item_int_func } longlong val_int(); void fix_length_and_dec(); - ~Item_func_in() {} + ~Item_func_in() + { + cleanup(); /* This is not called by Item::~Item() */ + } void cleanup() { delete array; diff --git a/sql/item_func.cc b/sql/item_func.cc index 7e03f8c9c45..10e405393a2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1634,7 +1634,7 @@ bool udf_handler::get_arguments() String *udf_handler::val_str(String *str,String *save_str) { - uchar is_null=0; + uchar is_null_tmp=0; ulong res_length; if (get_arguments()) @@ -1651,9 +1651,9 @@ String *udf_handler::val_str(String *str,String *save_str) return 0; } } - char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length, &is_null, - &error); - if (is_null || !res || error) // The !res is for safety + char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length, + &is_null_tmp, &error); + if (is_null_tmp || !res || error) // The !res is for safety { return 0; } @@ -2331,9 +2331,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, bool Item_func_set_user_var::check() { - bool res; DBUG_ENTER("Item_func_set_user_var::check"); - LINT_INIT(res); switch (cached_result_type) { case REAL_RESULT: @@ -2712,6 +2710,7 @@ void Item_func_match::init_search(bool no_order) bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { Item *item; + LINT_INIT(item); // Safe as arg_count is > 1 maybe_null=1; join_key=0; @@ -2722,7 +2721,8 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) modifications to find_best and auto_close as complement to auto_init code above. */ - if (Item_func::fix_fields(thd, tlist, ref) || !args[0]->const_item()) + if (Item_func::fix_fields(thd, tlist, ref) || + !args[0]->const_during_execution()) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST"); return 1; @@ -2736,11 +2736,15 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) args[i]= item= *((Item_ref *)item)->ref; if (item->type() != Item::FIELD_ITEM) key=NO_SUCH_KEY; - used_tables_cache|=item->used_tables(); } - /* check that all columns come from the same table */ - if (my_count_bits(used_tables_cache) != 1) + /* + Check that all columns come from the same table. + We've already checked that columns in MATCH are fields so + PARAM_TABLE_BIT can only appear from AGAINST argument. + */ + if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables()) key=NO_SUCH_KEY; + if (key == NO_SUCH_KEY && !(flags & FT_BOOL)) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH"); @@ -3022,7 +3026,6 @@ longlong Item_func_is_free_lock::val_int() String *res=args[0]->val_str(&value); THD *thd=current_thd; ULL *ull; - int error=0; null_value=0; if (!res || !res->length()) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index dfaf3001a19..f40d38dd4a8 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -324,7 +324,6 @@ null: void Item_func_concat::fix_length_and_dec() { - bool first_coll= 1; max_length=0; if (agg_arg_collations(collation, args, arg_count)) @@ -2018,7 +2017,7 @@ void Item_func_lpad::fix_length_and_dec() String *Item_func_lpad::val_str(String *str) { - uint32 res_byte_length,res_char_length,pad_byte_length,pad_char_length; + uint32 res_char_length,pad_char_length; ulong count= (long) args[1]->val_int(), byte_count; String a1,a3; String *res= args[0]->val_str(&a1); @@ -2028,7 +2027,6 @@ String *Item_func_lpad::val_str(String *str) goto err; null_value=0; - res_byte_length= res->length(); res_char_length= res->numchars(); if (count <= res_char_length) @@ -2037,7 +2035,6 @@ String *Item_func_lpad::val_str(String *str) return res; } - pad_byte_length= pad->length(); pad_char_length= pad->numchars(); byte_count= count * collation.collation->mbmaxlen; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3ed137d0731..6f5e2e492e7 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -306,8 +306,7 @@ void Item_singlerow_subselect::fix_length_and_dec() } else { - THD *thd= current_thd; - if (!(row= (Item_cache**)thd->alloc(sizeof(Item_cache*)*max_columns))) + if (!(row= (Item_cache**) sql_alloc(sizeof(Item_cache*)*max_columns))) return; engine->fix_length_and_dec(row); value= *row; @@ -550,8 +549,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, SELECT_LEX *select_lex= join->select_lex; - THD *thd= join->thd; - thd->where= "scalar IN/ALL/ANY subquery"; + THD *thd_tmp= join->thd; + thd_tmp->where= "scalar IN/ALL/ANY subquery"; if (select_lex->item_list.elements > 1) { @@ -595,7 +594,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->item_list.empty(); select_lex->item_list.push_back(item); - if (item->fix_fields(thd, join->tables_list, &item)) + if (item->fix_fields(thd_tmp, join->tables_list, &item)) { DBUG_RETURN(RES_ERROR); } @@ -609,14 +608,14 @@ Item_in_subselect::single_value_transformer(JOIN *join, subs= new Item_maxmin_subselect(this, select_lex, func->l_op()); } // left expression belong to outer select - SELECT_LEX *current= thd->lex->current_select, *up; - thd->lex->current_select= up= current->return_after_parsing(); - if (left_expr->fix_fields(thd, up->get_table_list(), &left_expr)) + SELECT_LEX *current= thd_tmp->lex->current_select, *up; + thd_tmp->lex->current_select= up= current->return_after_parsing(); + if (left_expr->fix_fields(thd_tmp, up->get_table_list(), &left_expr)) { - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; DBUG_RETURN(RES_ERROR); } - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; substitution= func->create(left_expr, subs); DBUG_RETURN(RES_OK); } @@ -627,16 +626,16 @@ Item_in_subselect::single_value_transformer(JOIN *join, SELECT_LEX_UNIT *unit= select_lex->master_unit(); substitution= optimizer= new Item_in_optimizer(left_expr, this); - SELECT_LEX *current= thd->lex->current_select, *up; + SELECT_LEX *current= thd_tmp->lex->current_select, *up; - thd->lex->current_select= up= current->return_after_parsing(); + thd_tmp->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd_tmp, up->get_table_list(), 0)) { - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; DBUG_RETURN(RES_ERROR); } - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; /* As far as Item_ref_in_optimizer do not substitude itself on fix_fields @@ -664,7 +663,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, this->full_name())); join->having= and_items(join->having, item); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, &join->having)) + if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having)) { select_lex->having_fix_field= 0; DBUG_RETURN(RES_ERROR); @@ -688,7 +687,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, new Item_cond_and(having, join->having) : having); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, &join->having)) + if (join->having->fix_fields(thd_tmp, join->tables_list, + &join->having)) { select_lex->having_fix_field= 0; DBUG_RETURN(RES_ERROR); @@ -699,7 +699,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, } item->name= (char *)in_additional_cond; join->conds= and_items(join->conds, item); - if (join->conds->fix_fields(thd, join->tables_list, &join->conds)) + if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->conds)) DBUG_RETURN(RES_ERROR); } else @@ -711,7 +711,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, (char *)"<no matter>", (char *)"<result>")); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, &join->having)) + if (join->having->fix_fields(thd_tmp, join->tables_list, + &join->having)) { select_lex->having_fix_field= 0; DBUG_RETURN(RES_ERROR); @@ -725,11 +726,11 @@ Item_in_subselect::single_value_transformer(JOIN *join, // fix_field of item will be done in time of substituting substitution= item; have_to_be_excluded= 1; - if (thd->lex->describe) + if (thd_tmp->lex->describe) { char warn_buff[MYSQL_ERRMSG_SIZE]; sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + push_warning(thd_tmp, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } DBUG_RETURN(RES_REDUCE); @@ -739,13 +740,14 @@ Item_in_subselect::single_value_transformer(JOIN *join, DBUG_RETURN(RES_OK); } + Item_subselect::trans_res Item_in_subselect::row_value_transformer(JOIN *join) { DBUG_ENTER("Item_in_subselect::row_value_transformer"); - THD *thd= join->thd; - thd->where= "row IN/ALL/ANY subquery"; + THD *thd_tmp= join->thd; + thd_tmp->where= "row IN/ALL/ANY subquery"; SELECT_LEX *select_lex= join->select_lex; @@ -761,22 +763,22 @@ Item_in_subselect::row_value_transformer(JOIN *join) SELECT_LEX_UNIT *unit= select_lex->master_unit(); substitution= optimizer= new Item_in_optimizer(left_expr, this); - SELECT_LEX *current= thd->lex->current_select, *up; - thd->lex->current_select= up= current->return_after_parsing(); + SELECT_LEX *current= thd_tmp->lex->current_select, *up; + thd_tmp->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd_tmp, up->get_table_list(), 0)) { - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; DBUG_RETURN(RES_ERROR); } - thd->lex->current_select= current; + thd_tmp->lex->current_select= current; unit->uncacheable|= UNCACHEABLE_DEPENDENT; } uint n= left_expr->cols(); select_lex->uncacheable|= UNCACHEABLE_DEPENDENT; - select_lex->setup_ref_array(thd, + select_lex->setup_ref_array(thd_tmp, select_lex->order_list.elements + select_lex->group_list.elements); Item *item= 0; @@ -802,7 +804,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) { join->having= and_items(join->having, item); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, &join->having)) + if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having)) { select_lex->having_fix_field= 0; DBUG_RETURN(RES_ERROR); @@ -812,7 +814,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) else { join->conds= and_items(join->conds, item); - if (join->conds->fix_fields(thd, join->tables_list, &join->having)) + if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->having)) DBUG_RETURN(RES_ERROR); } DBUG_RETURN(RES_OK); @@ -880,7 +882,7 @@ subselect_single_select_engine(st_select_lex *select, unit->select_limit_cnt= unit->global_parameters->select_limit+ unit->global_parameters ->offset_limit; if (unit->select_limit_cnt < unit->global_parameters->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; // no limit + unit->select_limit_cnt= HA_POS_ERROR; // no limit if (unit->select_limit_cnt == HA_POS_ERROR) select_lex->options&= ~OPTION_FOUND_ROWS; unit->item= item; @@ -889,17 +891,17 @@ subselect_single_select_engine(st_select_lex *select, subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, - select_subselect *result, - Item_subselect *item) - :subselect_engine(item, result) + select_subselect *result_arg, + Item_subselect *item_arg) + :subselect_engine(item_arg, result_arg) { unit= u; - if (!result) - //out of memory + if (!result_arg) //out of memory current_thd->fatal_error(); - unit->item= item; + unit->item= item_arg; } + int subselect_single_select_engine::prepare() { if (prepared) @@ -907,8 +909,7 @@ int subselect_single_select_engine::prepare() join= new JOIN(thd, select_lex->item_list, select_lex->options, result); if (!join || !result) { - //out of memory - thd->fatal_error(); + thd->fatal_error(); //out of memory return 1; } prepared= 1; @@ -924,7 +925,7 @@ int subselect_single_select_engine::prepare() (ORDER*) select_lex->group_list.first, select_lex->having, (ORDER*) 0, select_lex, - select_lex->master_unit(), 0)) + select_lex->master_unit())) return 1; thd->lex->current_select= save_select; return 0; @@ -932,7 +933,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result, 0); + return unit->prepare(thd, result); } int subselect_uniquesubquery_engine::prepare() @@ -942,12 +943,12 @@ int subselect_uniquesubquery_engine::prepare() return 1; } -static Item_result set_row(SELECT_LEX *select_lex, Item * item, +static Item_result set_row(List<Item> &item_list, Item *item, Item_cache **row, bool *maybe_null) { Item_result res_type= STRING_RESULT; Item *sel_item; - List_iterator_fast<Item> li(select_lex->item_list); + List_iterator_fast<Item> li(item_list); for (uint i= 0; (sel_item= li++); i++) { item->max_length= sel_item->max_length; @@ -962,7 +963,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, row[i]->collation.set(sel_item->collation); } } - if (select_lex->item_list.elements > 1) + if (item_list.elements > 1) res_type= ROW_RESULT; return res_type; } @@ -970,7 +971,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) { DBUG_ASSERT(row || select_lex->item_list.elements==1); - res_type= set_row(select_lex, item, row, &maybe_null); + res_type= set_row(select_lex->item_list, item, row, &maybe_null); item->collation.set(row[0]->collation); if (cols() != 1) maybe_null= 0; @@ -981,44 +982,11 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) DBUG_ASSERT(row || unit->first_select()->item_list.elements==1); if (unit->first_select()->item_list.elements == 1) - { - uint32 mlen= 0, len; - Item *sel_item= 0; - for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) - { - List_iterator_fast<Item> li(sl->item_list); - Item *s_item= li++; - if ((len= s_item->max_length) > mlen) - mlen= len; - if (!sel_item) - sel_item= s_item; - maybe_null= s_item->maybe_null; - } - item->max_length= mlen; - res_type= sel_item->result_type(); - item->decimals= sel_item->decimals; - if (row) - { - if (!(row[0]= Item_cache::get_cache(res_type))) - return; - row[0]->set_len_n_dec(mlen, sel_item->decimals); - } - } + res_type= set_row(unit->types, item, row, &maybe_null); else { - SELECT_LEX *sl= unit->first_select(); bool fake= 0; - res_type= set_row(sl, item, row, &fake); - for (sl= sl->next_select(); sl; sl= sl->next_select()) - { - List_iterator_fast<Item> li(sl->item_list); - Item *sel_item; - for (uint i= 0; (sel_item= li++); i++) - { - if (sel_item->max_length > row[i]->max_length) - row[i]->max_length= sel_item->max_length; - } - } + res_type= set_row(unit->types, item, row, &fake); } } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 3637e025d3c..8444dc7bf66 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -263,7 +263,7 @@ public: virtual ~subselect_engine() {}; // to satisfy compiler // set_thd should be called before prepare() - void set_thd(THD *thd) { this->thd= thd; } + void set_thd(THD *thd_arg) { thd= thd_arg; } THD * get_thd() { return thd; } virtual int prepare()= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; @@ -328,11 +328,11 @@ protected: public: // constructor can assign THD because it will be called after JOIN::prepare - subselect_uniquesubquery_engine(THD *thd, st_join_table *tab_arg, + subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg, Item_subselect *subs, Item *where) :subselect_engine(subs, 0), tab(tab_arg), cond(where) { - set_thd(thd); + set_thd(thd_arg); } ~subselect_uniquesubquery_engine(); int prepare(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f179e2c40d1..a3d652d2fe1 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -104,16 +104,16 @@ Item *Item_sum::get_tmp_table_item(THD *thd) Item_sum* sum_item= (Item_sum *) copy_or_same(thd); if (sum_item && sum_item->result_field) // If not a const sum func { - Field *result_field= sum_item->result_field; + Field *result_field_tmp= sum_item->result_field; for (uint i=0 ; i < sum_item->arg_count ; i++) { Item *arg= sum_item->args[i]; if (!arg->const_item()) { if (arg->type() == Item::FIELD_ITEM) - ((Item_field*) arg)->field= result_field++; + ((Item_field*) arg)->field= result_field_tmp++; else - sum_item->args[i]= new Item_field(result_field++); + sum_item->args[i]= new Item_field(result_field_tmp++); } } } @@ -1642,10 +1642,8 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, original= 0; quick_group= 0; mark_as_sum_func(); - item_thd= current_thd; - SELECT_LEX *select_lex= item_thd->lex->current_select; order= 0; - group_concat_max_len= item_thd->variables.group_concat_max_len; + group_concat_max_len= current_thd->variables.group_concat_max_len; arg_show_fields= arg_count_field= is_select->elements; @@ -1791,6 +1789,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) thd->allow_sum_func= 0; maybe_null= 0; + item_thd= thd; for (i= 0 ; i < arg_count ; i++) { if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1)) @@ -1969,6 +1968,7 @@ String* Item_func_group_concat::val_str(String* str) return &result; } + void Item_func_group_concat::print(String *str) { str->append("group_concat(", 13); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index bcb7ddb1054..a5372a4ae60 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -137,14 +137,12 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, static bool extract_date_time(DATE_TIME_FORMAT *format, const char *val, uint length, TIME *l_time) { - int weekday= 0, yearday= 0, daypart= 0, len; + int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; CHARSET_INFO *cs= &my_charset_bin; int error= 0; bool usa_time= 0; bool sunday_first= 0; - uint part_len= 0; - const char *val_ptr= val; const char *val_end= val + length; const char *ptr= format->format.str; const char *end= ptr+ format->format.length; @@ -237,7 +235,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, /* Second part */ case 'f': tmp= (char*) val_end; - l_time->second_part= my_strtoll10(val, &tmp, &error); + l_time->second_part= (int) my_strtoll10(val, &tmp, &error); val= tmp; break; @@ -673,7 +671,7 @@ longlong Item_func_month::val_int() String* Item_func_monthname::val_str(String* str) { - const char *name; + const char *month_name; uint month=(uint) Item_func_month::val_int(); if (!month) // This is also true for NULL @@ -682,8 +680,8 @@ String* Item_func_monthname::val_str(String* str) return (String*) 0; } null_value=0; - name= month_names[month-1]; - str->set(name, strlen(name), system_charset_info); + month_name= month_names[month-1]; + str->set(month_name, strlen(month_name), system_charset_info); return str; } @@ -1221,7 +1219,7 @@ String *Item_func_sec_to_time::val_str(String *str) sec= (uint) ((ulonglong) seconds % 3600); ltime.day= 0; - ltime.hour= seconds/3600; + ltime.hour= (uint) (seconds/3600); ltime.minute= sec/60; ltime.second= sec % 60; @@ -1385,7 +1383,6 @@ String *Item_func_from_unixtime::val_str(String *str) { struct tm tm_tmp,*start; time_t tmp=(time_t) args[0]->val_int(); - CHARSET_INFO *cs= &my_charset_bin; TIME ltime; if ((null_value=args[0]->null_value)) @@ -1759,6 +1756,7 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const return 1; } + void Item_typecast::print(String *str) { str->append("cast(", 5); @@ -1768,6 +1766,7 @@ void Item_typecast::print(String *str) str->append(')'); } + void Item_char_typecast::print(String *str) { str->append("cast(", 5); @@ -1851,9 +1850,8 @@ String *Item_datetime_typecast::val_str(String *str) if (!get_arg0_date(<ime,1) && !make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME, <ime, str)) - return str; + return str; -null_date: null_value=1; return 0; } @@ -1912,8 +1910,8 @@ String *Item_date_typecast::val_str(String *str) String *Item_func_makedate::val_str(String *str) { TIME l_time; - long daynr= args[1]->val_int(); - long yearnr= args[0]->val_int(); + long daynr= (long) args[1]->val_int(); + long yearnr= (long) args[0]->val_int(); long days; if (args[0]->null_value || args[1]->null_value || @@ -1921,7 +1919,7 @@ String *Item_func_makedate::val_str(String *str) goto err; days= calc_daynr(yearnr,1,1) + daynr - 1; - // Day number from year 0 to 9999-12-31 + /* Day number from year 0 to 9999-12-31 */ if (days >= 0 && days < MAX_DAY_NUMBER) { null_value=0; @@ -2125,7 +2123,8 @@ String *Item_func_timediff::val_str(String *str) microseconds= l_time1.second_part - l_sign*l_time2.second_part; seconds= ((longlong) days*86400L + l_time1.hour*3600L + l_time1.minute*60L + l_time1.second + microseconds/1000000L - - (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+l_time2.second)); + (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+ + l_time2.second)); l_time3.neg= 0; if (seconds < 0) @@ -2146,7 +2145,7 @@ String *Item_func_timediff::val_str(String *str) if ((l_time2.neg == l_time1.neg) && l_time1.neg) l_time3.neg= l_time3.neg ? 0 : 1; - calc_time_from_sec(&l_time3, seconds, microseconds); + calc_time_from_sec(&l_time3, (long) seconds, microseconds); if (!make_datetime(l_time1.second_part || l_time2.second_part ? TIME_MICROSECOND : TIME_ONLY, @@ -2168,9 +2167,9 @@ String *Item_func_maketime::val_str(String *str) { TIME ltime; - long hour= args[0]->val_int(); - long minute= args[1]->val_int(); - long second= args[2]->val_int(); + long hour= (long) args[0]->val_int(); + long minute= (long) args[1]->val_int(); + long second= (long) args[2]->val_int(); if ((null_value=(args[0]->null_value || args[1]->null_value || @@ -2186,9 +2185,9 @@ String *Item_func_maketime::val_str(String *str) ltime.neg= 1; hour= -hour; } - ltime.hour= (ulong)hour; - ltime.minute= (ulong)minute; - ltime.second= (ulong)second; + ltime.hour= (ulong) hour; + ltime.minute= (ulong) minute; + ltime.second= (ulong) second; make_time((DATE_TIME_FORMAT *) 0, <ime, str); return str; } diff --git a/sql/log.cc b/sql/log.cc index f8e7c5ecb4e..95ee4928971 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -179,7 +179,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, const char *new_name, const char *index_file_name_arg, enum cache_type io_cache_type_arg, bool no_auto_events_arg, - ulong max_size) + ulong max_size_arg) { char buff[512]; File file= -1, index_file_nr= -1; @@ -190,7 +190,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, last_time=query_start=0; write_error=0; - init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size); + init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size_arg); if (!(name=my_strdup(log_name,MYF(MY_WME)))) goto err; @@ -1682,7 +1682,7 @@ void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave) const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log, master_or_slave ? "Has read all relay log; waiting for \ -the I/O slave thread to update it" : +the slave I/O thread to update it" : "Has sent all binlog to slave; \ waiting for binlog to be updated"); pthread_cond_wait(&update_cond, &LOCK_log); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7cf276cb31e..a393e80f978 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -432,8 +432,6 @@ bool check_stack_overrun(THD *thd,char *dummy); void table_cache_init(void); void table_cache_free(void); uint cached_tables(void); -void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt, - KEY_CACHE_VAR *new_key_cache); 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, @@ -466,8 +464,8 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list, LEX_STRING *key_cache_name); int mysql_preload_keys(THD* thd, TABLE_LIST* table_list); -int reassign_keycache_tables(THD* thd, KEY_CACHE_VAR *src_cache, - KEY_CACHE_VAR *dst_cache); +int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache, + KEY_CACHE *dst_cache); bool check_simple_select(); @@ -484,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_type, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool tables_and_fields_initied); + SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); @@ -493,7 +491,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex, select_result *result, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); + SELECT_LEX_UNIT *unit); int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, @@ -677,7 +675,6 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, List<Item> &item, bool set_query_id, List<Item> *sum_func_list, bool allow_sum_func); -void unfix_item_list(List<Item> item_list); int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); @@ -870,8 +867,7 @@ extern SHOW_COMP_OPTION have_berkeley_db; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct rand_struct sql_rand; -extern KEY_CACHE_VAR *sql_key_cache; -extern KEY_CACHE_HANDLE sql_key_cache_handle; +extern KEY_CACHE *sql_key_cache; extern const char *opt_date_time_formats[]; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0f2968b464e..1108be6e1b5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -358,7 +358,7 @@ struct system_variables max_system_variables; MY_TMPDIR mysql_tmpdir_list; MY_BITMAP temp_pool; -KEY_CACHE_VAR *sql_key_cache; +KEY_CACHE *sql_key_cache; CHARSET_INFO *system_charset_info, *files_charset_info ; CHARSET_INFO *national_charset_info, *table_alias_charset; @@ -1568,14 +1568,14 @@ We will try our best to scrape up some info that will hopefully help diagnose\n\ the problem, but since we have already crashed, something is definitely wrong\n\ and this may fail.\n\n"); fprintf(stderr, "key_buffer_size=%lu\n", - (ulong) sql_key_cache->buff_size); + (ulong) sql_key_cache->key_cache_mem_size); fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size); fprintf(stderr, "max_used_connections=%ld\n", max_used_connections); fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "threads_connected=%d\n", thread_count); fprintf(stderr, "It is possible that mysqld could use up to \n\ key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\ -bytes of memory\n", ((ulong) sql_key_cache->buff_size + +bytes of memory\n", ((ulong) sql_key_cache->key_cache_mem_size + (global_system_variables.read_buff_size + global_system_variables.sortbuff_size) * max_connections)/ 1024); @@ -2044,7 +2044,6 @@ bool init_global_datetime_format(timestamp_type format_type, { /* Get command line option */ const char *str= opt_date_time_formats[format_type]; - DATE_TIME_FORMAT *format; if (!str) // No specified format { @@ -2075,6 +2074,8 @@ static int init_common_variables(const char *conf_file_name, int argc, max_system_variables.pseudo_thread_id= (ulong)~0; start_time=time((time_t*) 0); + if (init_thread_environment()) + return 1; mysql_init_variables(); #ifdef OS2 @@ -2117,8 +2118,6 @@ static int init_common_variables(const char *conf_file_name, int argc, load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; get_options(argc,argv); - if (init_thread_environment()) - return 1; if (opt_log || opt_update_log || opt_slow_log || opt_bin_log) strcat(server_version,"-log"); DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, @@ -2379,7 +2378,7 @@ Now disabling --log-slave-updates."); /* call ha_init_key_cache() on all key caches to init them */ process_key_caches(&ha_init_key_cache); /* We must set dflt_key_cache in case we are using ISAM tables */ - dflt_keycache= &sql_key_cache->cache; + dflt_key_cache= sql_key_cache; #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) if (locked_in_memory && !geteuid()) @@ -3374,35 +3373,22 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) #ifdef HAVE_SMEM pthread_handler_decl(handle_connections_shared_memory,arg) { -/* - event_connect_request is event object for start connection actions - event_connect_answer is event object for confirm, that server put data - handle_connect_file_map is file-mapping object, use for create shared memory - handle_connect_map is pointer on shared memory - handle_map is pointer on shared memory for client - event_server_wrote, - event_server_read, - event_client_wrote, - event_client_read are events for transfer data between server and client - handle_file_map is file-mapping object, use for create shared memory -*/ - HANDLE handle_connect_file_map = NULL; - char *handle_connect_map = NULL; - HANDLE event_connect_request = NULL; - HANDLE event_connect_answer = NULL; - ulong smem_buffer_length = shared_memory_buffer_length + 4; - ulong connect_number = 1; + /* file-mapping object, use for create shared memory */ + HANDLE handle_connect_file_map= 0; + char *handle_connect_map= 0; // pointer on shared memory + HANDLE event_connect_request= 0; // for start connection actions + HANDLE event_connect_answer= 0; + ulong smem_buffer_length= shared_memory_buffer_length + 4; + ulong connect_number= 1; my_bool error_allow; - THD *thd; char tmp[63]; char *suffix_pos; char connect_number_char[22], *p; - + const char *errmsg= 0; my_thread_init(); DBUG_ENTER("handle_connections_shared_memorys"); DBUG_PRINT("general",("Waiting for allocated shared memory.")); - /* The name of event and file-mapping events create agree next rule: shared_memory_base_name+unique_part @@ -3410,166 +3396,165 @@ pthread_handler_decl(handle_connections_shared_memory,arg) shared_memory_base_name is unique value for each server unique_part is unique value for each object (events and file-mapping) */ - suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); + suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS); strmov(suffix_pos, "CONNECT_REQUEST"); - if ((event_connect_request = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create shared memory service ! The request event don't create."); + errmsg= "Could not create request event"; goto error; } strmov(suffix_pos, "CONNECT_ANSWER"); - if ((event_connect_answer = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_connect_answer= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create shared memory service ! The answer event don't create."); + errmsg="Could not create answer event"; goto error; } strmov(suffix_pos, "CONNECT_DATA"); - if ((handle_connect_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE, - 0,sizeof(connect_number),tmp)) == 0) + if ((handle_connect_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0, + PAGE_READWRITE, + 0,sizeof(connect_number), + tmp)) == 0) { - sql_perror("Can't create shared memory service ! File mapping don't create."); + errmsg= "Could not create file mapping"; goto error; } - if ((handle_connect_map = (char *)MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0, - sizeof(DWORD))) == 0) + if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map, + FILE_MAP_WRITE,0,0, + sizeof(DWORD))) == 0) { - sql_perror("Can't create shared memory service ! Map of memory don't create."); + errmsg= "Could not create shared memory service"; goto error; } - while (!abort_loop) { -/* - Wait a request from client -*/ + /* Wait a request from client */ WaitForSingleObject(event_connect_request,INFINITE); - error_allow = FALSE; - HANDLE handle_client_file_map = NULL; - char *handle_client_map = NULL; - HANDLE event_client_wrote = NULL; - HANDLE event_client_read = NULL; - HANDLE event_server_wrote = NULL; - HANDLE event_server_read = NULL; + HANDLE handle_client_file_map= 0; + char *handle_client_map= 0; + HANDLE event_client_wrote= 0; + HANDLE event_client_read= 0; // for transfer data server <-> client + HANDLE event_server_wrote= 0; + HANDLE event_server_read= 0; + THD *thd= 0; - p = int2str(connect_number, connect_number_char, 10); -/* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part+number_of_connection - Where: - shared_memory_base_name is uniquel value for each server - unique_part is unique value for each object (events and file-mapping) - number_of_connection is number of connection between server and client -*/ - suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,"_",NullS); + p= int2str(connect_number, connect_number_char, 10); + /* + The name of event and file-mapping events create agree next rule: + shared_memory_base_name+unique_part+number_of_connection + Where: + shared_memory_base_name is uniquel value for each server + unique_part is unique value for each object (events and file-mapping) + number_of_connection is connection-number between server and client + */ + suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char, + "_",NullS); strmov(suffix_pos, "DATA"); - if ((handle_client_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL, - PAGE_READWRITE,0,smem_buffer_length,tmp)) == 0) + if ((handle_client_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0, + PAGE_READWRITE,0, + smem_buffer_length, + tmp)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! File mapping don't create."); - error_allow = TRUE; + errmsg= "Could not create file mapping"; goto errorconn; } - if ((handle_client_map = (char*)MapViewOfFile(handle_client_file_map,FILE_MAP_WRITE,0,0,smem_buffer_length)) == 0) + if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map, + FILE_MAP_WRITE,0,0, + smem_buffer_length)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! Map of memory don't create."); - error_allow = TRUE; + errmsg= "Could not create memory map"; goto errorconn; } - strmov(suffix_pos, "CLIENT_WROTE"); - if ((event_client_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_client_wrote= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! CW event don't create."); - error_allow = TRUE; + errmsg= "Could not create client write event"; goto errorconn; } - strmov(suffix_pos, "CLIENT_READ"); - if ((event_client_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_client_read= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! CR event don't create."); - error_allow = TRUE; + errmsg= "Could not create client read event"; goto errorconn; } - strmov(suffix_pos, "SERVER_READ"); - if ((event_server_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_server_read= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! SR event don't create."); - error_allow = TRUE; + errmsg= "Could not create server read event"; goto errorconn; } - strmov(suffix_pos, "SERVER_WROTE"); - if ((event_server_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0) + if ((event_server_wrote= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { - sql_perror("Can't create connection with client in shared memory service ! SW event don't create."); - error_allow = TRUE; + errmsg= "Could not create server write event"; goto errorconn; } - - if (abort_loop) break; - if ( !(thd = new THD)) - { - error_allow = TRUE; + if (abort_loop) goto errorconn; - } - -/* -Send number of connection to client -*/ + if (!(thd= new THD)) + goto errorconn; + /* Send number of connection to client */ int4store(handle_connect_map, connect_number); - -/* - Send number of connection to client -*/ if (!SetEvent(event_connect_answer)) { - sql_perror("Can't create connection with client in shared memory service ! Can't send answer event."); - error_allow = TRUE; + errmsg= "Could not send answer event"; goto errorconn; } - -/* - Set event that client should receive data -*/ + /* Set event that client should receive data */ if (!SetEvent(event_client_read)) { - sql_perror("Can't create connection with client in shared memory service ! Can't set client to read's mode."); - error_allow = TRUE; + errmsg= "Could not set client to read mode"; goto errorconn; } - if (!(thd->net.vio = vio_new_win32shared_memory(&thd->net,handle_client_file_map,handle_client_map,event_client_wrote, - event_client_read,event_server_wrote,event_server_read)) || - my_net_init(&thd->net, thd->net.vio)) + if (!(thd->net.vio= vio_new_win32shared_memory(&thd->net, + handle_client_file_map, + handle_client_map, + event_client_wrote, + event_client_read, + event_server_wrote, + event_server_read)) || + my_net_init(&thd->net, thd->net.vio)) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); - delete thd; - error_allow = TRUE; + errmsg= 0; + goto errorconn; } - /* host name is unknown */ + thd->host= my_strdup(my_localhost,MYF(0)); /* Host is unknown */ + create_new_thread(thd); + connect_number++; + continue; + errorconn: - if (error_allow) + /* Could not form connection; Free used handlers/memort and retry */ + if (errmsg) { - if (!handle_client_map) UnmapViewOfFile(handle_client_map); - if (!handle_client_file_map) CloseHandle(handle_client_file_map); - if (!event_server_wrote) CloseHandle(event_server_wrote); - if (!event_server_read) CloseHandle(event_server_read); - if (!event_client_wrote) CloseHandle(event_client_wrote); - if (!event_client_read) CloseHandle(event_client_read); - continue; + char buff[180]; + strxmov(buff, "Can't create shared memory connection: ", errmsg, ".", + NullS); + sql_perror(buff); } - thd->host = my_strdup(my_localhost,MYF(0)); /* Host is unknown */ - create_new_thread(thd); - uint4korr(connect_number++); + if (handle_client_file_map) CloseHandle(handle_client_file_map); + if (handle_client_map) UnmapViewOfFile(handle_client_map); + if (event_server_wrote) CloseHandle(event_server_wrote); + if (event_server_read) CloseHandle(event_server_read); + if (event_client_wrote) CloseHandle(event_client_wrote); + if (event_client_read) CloseHandle(event_client_read); + delete thd; } + + /* End shared memory handling */ error: - if (!handle_connect_map) UnmapViewOfFile(handle_connect_map); - if (!handle_connect_file_map) CloseHandle(handle_connect_file_map); - if (!event_connect_answer) CloseHandle(event_connect_answer); - if (!event_connect_request) CloseHandle(event_connect_request); + if (errmsg) + { + char buff[180]; + strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS); + sql_perror(buff); + } + if (handle_connect_map) UnmapViewOfFile(handle_connect_map); + if (handle_connect_file_map) CloseHandle(handle_connect_file_map); + if (event_connect_answer) CloseHandle(event_connect_answer); + if (event_connect_request) CloseHandle(event_connect_request); decrement_handler_count(); DBUG_RETURN(0); @@ -4370,26 +4355,26 @@ log and this option does nothing anymore.", IO_SIZE, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", - (gptr*) &dflt_key_cache_var.buff_size, + (gptr*) &dflt_key_cache_var.param_buff_size, (gptr*) 0, 0, (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "The default size of key cache blocks", - (gptr*) &dflt_key_cache_var.block_size, + (gptr*) &dflt_key_cache_var.param_block_size, (gptr*) 0, 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0}, {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT, "The minimum percentage of warm blocks in key cache", - (gptr*) &dflt_key_cache_var.division_limit, + (gptr*) &dflt_key_cache_var.param_division_limit, (gptr*) 0, 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0}, {"key_cache_division_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache", - (gptr*) &dflt_key_cache_var.age_threshold, + (gptr*) &dflt_key_cache_var.param_age_threshold, (gptr*) 0, 0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, 300, 100, ~0L, 0, 100, 0}, @@ -4811,17 +4796,17 @@ struct show_var_st status_vars[]= { {"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG}, {"Handler_update", (char*) &ha_update_count, SHOW_LONG}, {"Handler_write", (char*) &ha_write_count, SHOW_LONG}, - {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.blocks_changed, + {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed, SHOW_KEY_CACHE_LONG}, - {"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used, + {"Key_blocks_used", (char*) &dflt_key_cache_var.global_blocks_used, SHOW_KEY_CACHE_LONG}, - {"Key_read_requests", (char*) &dflt_key_cache_var.cache_r_requests, + {"Key_read_requests", (char*) &dflt_key_cache_var.global_cache_r_requests, SHOW_KEY_CACHE_LONG}, - {"Key_reads", (char*) &dflt_key_cache_var.cache_read, + {"Key_reads", (char*) &dflt_key_cache_var.global_cache_read, SHOW_KEY_CACHE_LONG}, - {"Key_write_requests", (char*) &dflt_key_cache_var.cache_w_requests, + {"Key_write_requests", (char*) &dflt_key_cache_var.global_cache_w_requests, SHOW_KEY_CACHE_LONG}, - {"Key_writes", (char*) &dflt_key_cache_var.cache_write, + {"Key_writes", (char*) &dflt_key_cache_var.global_cache_write, SHOW_KEY_CACHE_LONG}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST}, @@ -4894,8 +4879,8 @@ struct show_var_st status_vars[]= { static void print_version(void) { - printf("%s Ver %s for %s on %s\n",my_progname, - server_version,SYSTEM_TYPE,MACHINE_TYPE); + printf("%s Ver %s for %s on %s (%s)\n",my_progname, + server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT); } static void use_help(void) @@ -5662,18 +5647,18 @@ mysql_getopt_value(const char *keyname, uint key_length, case OPT_KEY_CACHE_DIVISION_LIMIT: case OPT_KEY_CACHE_AGE_THRESHOLD: { - KEY_CACHE_VAR *key_cache; + KEY_CACHE *key_cache; if (!(key_cache= get_or_create_key_cache(keyname, key_length))) exit(1); switch (option->id) { case OPT_KEY_BUFFER_SIZE: - return (gptr*) &key_cache->buff_size; + return (gptr*) &key_cache->param_buff_size; case OPT_KEY_CACHE_BLOCK_SIZE: - return (gptr*) &key_cache->block_size; + return (gptr*) &key_cache->param_block_size; case OPT_KEY_CACHE_DIVISION_LIMIT: - return (gptr*) &key_cache->division_limit; + return (gptr*) &key_cache->param_division_limit; case OPT_KEY_CACHE_AGE_THRESHOLD: - return (gptr*) &key_cache->age_threshold; + return (gptr*) &key_cache->param_age_threshold; } } } @@ -5854,63 +5839,80 @@ static void fix_paths(void) */ #ifdef SET_RLIMIT_NOFILE + +#ifndef RLIM_INFINITY +#define RLIM_INFINITY ((uint) 0xffffffff) +#endif + static uint set_maximum_open_files(uint max_file_limit) { struct rlimit rlimit; - ulong old_cur; + uint old_cur; + DBUG_ENTER("set_maximum_open_files"); + DBUG_PRINT("enter",("files: %u", max_file_limit)); if (!getrlimit(RLIMIT_NOFILE,&rlimit)) { - old_cur=rlimit.rlim_cur; - if (rlimit.rlim_cur >= max_file_limit) // Nothing to do - return rlimit.rlim_cur; /* purecov: inspected */ - rlimit.rlim_cur=rlimit.rlim_max=max_file_limit; + old_cur= (uint) rlimit.rlim_cur; + DBUG_PRINT("info", ("rlim_cur: %u rlim_max: %u", + (uint) rlimit.rlim_cur, + (uint) rlimit.rlim_max)); + if (rlimit.rlim_cur >= max_file_limit || + rlimit.rlim_cur == RLIM_INFINITY) + DBUG_RETURN(rlimit.rlim_cur); /* purecov: inspected */ + rlimit.rlim_cur= rlimit.rlim_max= max_file_limit; if (setrlimit(RLIMIT_NOFILE,&rlimit)) { if (global_system_variables.log_warnings) - sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %lu (request: %u)", + sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %u (request: %u)", old_cur, max_file_limit); /* purecov: inspected */ - max_file_limit=old_cur; + max_file_limit= old_cur; } else { + rlimit.rlim_cur= 0; // Safety if next call fails (void) getrlimit(RLIMIT_NOFILE,&rlimit); - if ((uint) rlimit.rlim_cur != max_file_limit && + DBUG_PRINT("info", ("rlim_cur: %u", (uint) rlimit.rlim_cur)); + if ((uint) rlimit.rlim_cur < max_file_limit && global_system_variables.log_warnings) - sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %ld (request: %u)", - (ulong) rlimit.rlim_cur, + sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %u (request: %u)", + (uint) rlimit.rlim_cur, max_file_limit); /* purecov: inspected */ - max_file_limit=rlimit.rlim_cur; + max_file_limit= (uint) rlimit.rlim_cur; } } - return max_file_limit; + DBUG_PRINT("exit",("max_file_limit: %u", max_file_limit)); + DBUG_RETURN(max_file_limit); } #endif + #ifdef OS2 static uint set_maximum_open_files(uint max_file_limit) { - LONG cbReqCount; - ULONG cbCurMaxFH, cbCurMaxFH0; - APIRET ulrc; - - // get current limit - cbReqCount = 0; - DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0); - - // set new limit - cbReqCount = max_file_limit - cbCurMaxFH0; - ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH); - if (ulrc) { - sql_print_error("Warning: DosSetRelMaxFH couldn't increase number of open files to more than %d", - cbCurMaxFH0); - cbCurMaxFH = cbCurMaxFH0; - } - - return cbCurMaxFH; + LONG cbReqCount; + ULONG cbCurMaxFH, cbCurMaxFH0; + APIRET ulrc; + DBUG_ENTER("set_maximum_open_files"); + + // get current limit + cbReqCount = 0; + DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0); + + // set new limit + cbReqCount = max_file_limit - cbCurMaxFH0; + ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH); + if (ulrc) { + sql_print_error("Warning: DosSetRelMaxFH couldn't increase number of open files to more than %d", + cbCurMaxFH0); + cbCurMaxFH = cbCurMaxFH0; + } + + DBUG_RETURN(cbCurMaxFH); } #endif + /* Return a bitfield from a string of substrings separated by ',' returns ~(ulong) 0 on error. diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0897340b5fa..93ba77f04ae 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -68,7 +68,7 @@ public: {} inline bool is_same(SEL_ARG *arg) { - if (type != arg->type) + if (type != arg->type || part != arg->part) return 0; if (type != KEY_RANGE) return 1; diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 932aceebdbb..4fdcd093132 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -83,7 +83,6 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) table_map removed_tables= 0, outer_tables= 0, used_tables= 0; table_map where_tables= 0; Item *item; - COND *org_conds= conds; int error; if (conds) diff --git a/sql/protocol.cc b/sql/protocol.cc index c28c1e1abb8..89aa7203e17 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -298,6 +298,12 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) pos=net_store_length(pos, (ulonglong) id); if (thd->client_capabilities & CLIENT_PROTOCOL_41) { + DBUG_PRINT("info", + ("affected_rows: %lu id: %lu status: %u warning_count: %u", + (ulong) affected_rows, + (ulong) id, + (uint) (thd->server_status & 0xffff), + (uint) thd->total_warn_count)); int2store(pos,thd->server_status); pos+=2; @@ -315,6 +321,8 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) pos=net_store_data((char*) pos, message, strlen(message)); VOID(my_net_write(net,buff,(uint) (pos-buff))); VOID(net_flush(net)); + /* We can't anymore send an error to the client */ + thd->net.report_error= 0; DBUG_VOID_RETURN; } @@ -494,7 +502,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) char buff[80]; String tmp((char*) buff,sizeof(buff),&my_charset_bin); Protocol_simple prot(thd); - String *packet= prot.storage_packet(); + String *local_packet= prot.storage_packet(); CHARSET_INFO *thd_charset= thd->variables.character_set_results; DBUG_ENTER("send_fields"); @@ -531,10 +539,10 @@ bool Protocol::send_fields(List<Item> *list, uint flag) cs, thd_charset) || prot.store(field.org_col_name, (uint) strlen(field.org_col_name), cs, thd_charset) || - packet->realloc(packet->length()+12)) + local_packet->realloc(local_packet->length()+12)) goto err; /* Store fixed length fields */ - pos= (char*) packet->ptr()+packet->length(); + pos= (char*) local_packet->ptr()+local_packet->length(); *pos++= 12; // Length of packed fields int2store(pos, field.charsetnr); int4store(pos+2, field.length); @@ -551,9 +559,9 @@ bool Protocol::send_fields(List<Item> *list, uint flag) cs, thd_charset) || prot.store(field.col_name, (uint) strlen(field.col_name), cs, thd_charset) || - packet->realloc(packet->length()+10)) + local_packet->realloc(local_packet->length()+10)) goto err; - pos= (char*) packet->ptr()+packet->length(); + pos= (char*) local_packet->ptr()+local_packet->length(); #ifdef TO_BE_DELETED_IN_6 if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) @@ -580,7 +588,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) pos+= 10; } } - packet->length((uint) (pos - packet->ptr())); + local_packet->length((uint) (pos - local_packet->ptr())); if (flag & 2) item->send(&prot, &tmp); // Send default value if (prot.write()) diff --git a/sql/protocol.h b/sql/protocol.h index 6aa9b6414ae..d2ec08c3cf4 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -44,9 +44,9 @@ protected: #endif public: Protocol() {} - Protocol(THD *thd) { init(thd); } + Protocol(THD *thd_arg) { init(thd_arg); } virtual ~Protocol() {} - void init(THD* thd); + void init(THD* thd_arg); virtual bool send_fields(List<Item> *list, uint flag); bool send_records_num(List<Item> *list, ulonglong records); bool store(I_List<i_string> *str_list); @@ -93,7 +93,7 @@ class Protocol_simple :public Protocol { public: Protocol_simple() {} - Protocol_simple(THD *thd) :Protocol(thd) {} + Protocol_simple(THD *thd_arg) :Protocol(thd_arg) {} virtual void prepare_for_resend(); virtual bool store_null(); virtual bool store_tiny(longlong from); @@ -118,7 +118,7 @@ private: uint bit_fields; public: Protocol_prep() {} - Protocol_prep(THD *thd) :Protocol(thd) {} + Protocol_prep(THD *thd_arg) :Protocol(thd_arg) {} virtual bool prepare_for_send(List<Item> *item_list); virtual void prepare_for_resend(); #ifdef EMBEDDED_LIBRARY @@ -151,7 +151,7 @@ public: ulong row_count; Protocol_cursor() {} - Protocol_cursor(THD *thd, MEM_ROOT *ini_alloc) :Protocol_simple(thd), alloc(ini_alloc) {} + Protocol_cursor(THD *thd_arg, MEM_ROOT *ini_alloc) :Protocol_simple(thd_arg), alloc(ini_alloc) {} bool prepare_for_send(List<Item> *item_list) { row_count= 0; @@ -171,7 +171,6 @@ void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); void send_eof(THD *thd, bool no_flush=0); bool send_old_password_request(THD *thd); -char *net_store_length(char *packet,ulonglong length); char *net_store_length(char *packet,uint length); char *net_store_data(char *to,const char *from, uint length); char *net_store_data(char *to,int32 from); diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc index abb391fbd67..b9e9c14f361 100644 --- a/sql/protocol_cursor.cc +++ b/sql/protocol_cursor.cc @@ -30,7 +30,7 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flag) { List_iterator_fast<Item> it(*list); Item *item; - MYSQL_FIELD *field, *client_field; + MYSQL_FIELD *client_field; DBUG_ENTER("send_fields"); if (prepare_for_send(list)) @@ -73,9 +73,9 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flag) String tmp(buff, sizeof(buff), default_charset_info), *res; if (!(res=item->val_str(&tmp))) - client_field->def= strdup_root(alloc, ""); + client_field->def= (char*) ""; else - client_field->def= strdup_root(alloc, tmp.ptr()); + client_field->def= strmake_root(alloc, res->ptr(), res->length()); } else client_field->def=0; @@ -98,23 +98,23 @@ bool Protocol_cursor::write() MYSQL_FIELD *cur_field= fields; MYSQL_FIELD *fields_end= fields + field_count; MYSQL_ROWS *new_record; - byte **data; + byte **data_tmp; byte *to; new_record= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS) + (field_count + 1)*sizeof(char *) + packet->length()); if (!new_record) goto err; - data= (byte **)(new_record + 1); - new_record->data= (char **)data; + data_tmp= (byte **)(new_record + 1); + new_record->data= (char **)data_tmp; to= (byte *)data + (field_count + 1)*sizeof(char *); - for (; cur_field < fields_end; ++cur_field, ++data) + for (; cur_field < fields_end; ++cur_field, ++data_tmp) { if ((len= net_field_length((uchar **)&cp)) == 0) { - *data= 0; + *data_tmp= 0; } else { diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 4d8d1380139..0efe57af0b0 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -254,7 +254,7 @@ static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg) it is reworked. Event's log_pos used to be preserved through log-slave-updates to make code in repl_failsafe.cc work (this function, SHOW NEW MASTER); but on the other side it caused unexpected - values in Exec_master_log_pos in A->B->C replication setup, + values in Exec_Master_Log_Pos in A->B->C replication setup, synchronization problems in master_pos_wait(), ... So we (Dmitri & Guilhem) removed it. @@ -623,7 +623,6 @@ err: int show_slave_hosts(THD* thd) { List<Item> field_list; - NET* net = &thd->net; Protocol *protocol= thd->protocol; DBUG_ENTER("show_slave_hosts"); @@ -909,7 +908,12 @@ int load_master_data(THD* thd) // don't hit the magic number if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE) active_mi->master_log_pos = BIN_LOG_HEADER_SIZE; - flush_master_info(active_mi); + /* + Relay log's IO_CACHE may not be inited (even if we are sure that some + host was specified; there could have been a problem when replication + started, which led to relay log's IO_CACHE to not be inited. + */ + flush_master_info(active_mi, 0); } mysql_free_result(master_status_res); } diff --git a/sql/set_var.cc b/sql/set_var.cc index dfbe7d60741..5912862f23b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -93,7 +93,7 @@ static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type); static void fix_max_connections(THD *thd, enum_var_type type); -static KEY_CACHE_VAR *create_key_cache(const char *name, uint length); +static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); @@ -145,14 +145,14 @@ sys_var_thd_ulong sys_join_buffer_size("join_buffer_size", &SV::join_buff_size); sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size"); sys_var_key_cache_long sys_key_cache_block_size("key_cache_block_size", - offsetof(KEY_CACHE_VAR, - block_size)); + offsetof(KEY_CACHE, + param_block_size)); sys_var_key_cache_long sys_key_cache_division_limit("key_cache_division_limit", - offsetof(KEY_CACHE_VAR, - division_limit)); + offsetof(KEY_CACHE, + param_division_limit)); sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold", - offsetof(KEY_CACHE_VAR, - age_threshold)); + offsetof(KEY_CACHE, + param_age_threshold)); sys_var_bool_ptr sys_local_infile("local_infile", &opt_local_infile); sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings); @@ -550,7 +550,6 @@ struct show_var_st init_vars[]= { {"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR}, {"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL}, {"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR}, - {"bdb_version", (char*) DB_VERSION_STRING, SHOW_CHAR}, #endif {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS}, {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS}, @@ -741,6 +740,12 @@ struct show_var_st init_vars[]= { SHOW_SYS}, {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, {"version", server_version, SHOW_CHAR}, +#ifdef HAVE_BERKELEY_DB + {"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR}, +#endif + {"version_comment", (char*) MYSQL_COMPILATION_COMMENT, SHOW_CHAR}, + {"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR}, + {"version_compile_os", (char*) SYSTEM_TYPE, SHOW_CHAR}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {NullS, NullS, SHOW_LONG} }; @@ -1779,15 +1784,14 @@ void sys_var_collation_server::set_default(THD *thd, enum_var_type type) LEX_STRING default_key_cache_base= {(char *) "default", 7 }; -static KEY_CACHE_VAR zero_key_cache= - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static KEY_CACHE zero_key_cache; -KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name) +KEY_CACHE *get_key_cache(LEX_STRING *cache_name) { safe_mutex_assert_owner(&LOCK_global_system_variables); if (!cache_name || ! cache_name->length) cache_name= &default_key_cache_base; - return ((KEY_CACHE_VAR*) find_named(&key_caches, + return ((KEY_CACHE*) find_named(&key_caches, cache_name->str, cache_name->length, 0)); } @@ -1795,7 +1799,7 @@ KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name) byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - KEY_CACHE_VAR *key_cache= get_key_cache(base); + KEY_CACHE *key_cache= get_key_cache(base); if (!key_cache) key_cache= &zero_key_cache; return (byte*) key_cache + offset ; @@ -1806,7 +1810,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; LEX_STRING *base_name= &var->base; - KEY_CACHE_VAR *key_cache; + KEY_CACHE *key_cache; bool error= 0; /* If no basename, assume it's for the key cache named 'default' */ @@ -1841,14 +1845,14 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) if (key_cache == sql_key_cache) goto end; // Ignore default key cache - if (key_cache->cache) // If initied + if (key_cache->key_cache_inited) // If initied { /* Move tables using this key cache to the default key cache and clear the old key cache. */ NAMED_LIST *list; - key_cache= (KEY_CACHE_VAR *) find_named(&key_caches, base_name->str, + key_cache= (KEY_CACHE *) find_named(&key_caches, base_name->str, base_name->length, &list); key_cache->in_init= 1; pthread_mutex_unlock(&LOCK_global_system_variables); @@ -1863,13 +1867,14 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) goto end; } - key_cache->buff_size= (ulonglong) getopt_ull_limit_value(tmp, option_limits); + key_cache->param_buff_size= + (ulonglong) getopt_ull_limit_value(tmp, option_limits); /* If key cache didn't existed initialize it, else resize it */ key_cache->in_init= 1; pthread_mutex_unlock(&LOCK_global_system_variables); - if (!key_cache->cache) + if (!key_cache->key_cache_inited) error= (bool) (ha_init_key_cache("", key_cache)); else error= (bool)(ha_resize_key_cache(key_cache)); @@ -1885,7 +1890,7 @@ end: bool sys_var_key_cache_long::update(THD *thd, set_var *var) { - ulong tmp= var->value->val_int(); + ulong tmp= (ulong) var->value->val_int(); LEX_STRING *base_name= &var->base; bool error= 0; @@ -1893,7 +1898,7 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) base_name= &default_key_cache_base; pthread_mutex_lock(&LOCK_global_system_variables); - KEY_CACHE_VAR *key_cache= get_key_cache(base_name); + KEY_CACHE *key_cache= get_key_cache(base_name); if (!key_cache && !(key_cache= create_key_cache(base_name->str, base_name->length))) @@ -2439,7 +2444,6 @@ byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, ulong val; char buff[256]; String tmp(buff, sizeof(buff), &my_charset_latin1); - my_bool found= 0; tmp.length(0); val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : @@ -2569,13 +2573,13 @@ void delete_elements(I_List<NAMED_LIST> *list, /* Key cache functions */ -static KEY_CACHE_VAR *create_key_cache(const char *name, uint length) +static KEY_CACHE *create_key_cache(const char *name, uint length) { - KEY_CACHE_VAR *key_cache; + KEY_CACHE *key_cache; DBUG_ENTER("create_key_cache"); DBUG_PRINT("enter",("name: %.*s", length, name)); - if ((key_cache= (KEY_CACHE_VAR*) my_malloc(sizeof(KEY_CACHE_VAR), + if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE), MYF(MY_ZEROFILL | MY_WME)))) { if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache)) @@ -2591,19 +2595,19 @@ static KEY_CACHE_VAR *create_key_cache(const char *name, uint length) We don't set 'buff_size' as this is used to enable the key cache */ - key_cache->block_size= dflt_key_cache_var.block_size; - key_cache->division_limit= dflt_key_cache_var.division_limit; - key_cache->age_threshold= dflt_key_cache_var.age_threshold; + key_cache->param_block_size= dflt_key_cache_var.param_block_size; + key_cache->param_division_limit= dflt_key_cache_var.param_division_limit; + key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold; } } DBUG_RETURN(key_cache); } -KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length) +KEY_CACHE *get_or_create_key_cache(const char *name, uint length) { LEX_STRING key_cache_name; - KEY_CACHE_VAR *key_cache; + KEY_CACHE *key_cache; key_cache_name.str= (char *) name; key_cache_name.length= length; @@ -2615,21 +2619,21 @@ KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length) } -void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache) +void free_key_cache(const char *name, KEY_CACHE *key_cache) { ha_end_key_cache(key_cache); my_free((char*) key_cache, MYF(0)); } -bool process_key_caches(int (* func) (const char *name, KEY_CACHE_VAR *)) +bool process_key_caches(int (* func) (const char *name, KEY_CACHE *)) { I_List_iterator<NAMED_LIST> it(key_caches); NAMED_LIST *element; while ((element= it++)) { - KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) element->data; + KEY_CACHE *key_cache= (KEY_CACHE *) element->data; func(element->name, key_cache); } return 0; diff --git a/sql/set_var.h b/sql/set_var.h index a4c3b546fe0..58ae53190e0 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -560,7 +560,7 @@ class sys_var_key_buffer_size :public sys_var_key_cache_param { public: sys_var_key_buffer_size(const char *name_arg) - :sys_var_key_cache_param(name_arg, offsetof(KEY_CACHE_VAR, buff_size)) + :sys_var_key_cache_param(name_arg, offsetof(KEY_CACHE, param_buff_size)) {} bool update(THD *thd, set_var *var); SHOW_TYPE type() { return SHOW_LONGLONG; } @@ -755,7 +755,7 @@ public: my_free((char*) name, MYF(0)); } friend bool process_key_caches(int (* func) (const char *name, - KEY_CACHE_VAR *)); + KEY_CACHE *)); friend void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(const char*, gptr)); }; @@ -788,6 +788,9 @@ gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length, NAMED_LIST **found); /* key_cache functions */ -KEY_CACHE_VAR *get_key_cache(LEX_STRING *cache_name); -KEY_CACHE_VAR *get_or_create_key_cache(const char *name, uint length); -void free_key_cache(const char *name, KEY_CACHE_VAR *key_cache); +KEY_CACHE *get_key_cache(LEX_STRING *cache_name); +KEY_CACHE *get_or_create_key_cache(const char *name, uint length); +void free_key_cache(const char *name, KEY_CACHE *key_cache); +bool process_key_caches(int (* func) (const char *name, KEY_CACHE *)); +void delete_elements(I_List<NAMED_LIST> *list, + void (*free_element)(const char*, gptr)); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 4dba54823ec..5cf1dd2a47c 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -296,6 +296,7 @@ character-set=latin2 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 07cbc84be14..69e14c6acf3 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -290,6 +290,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 8731c94fcdd..386ff34ef59 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -298,6 +298,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 9f93925a1ac..2e159d40e40 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -287,6 +287,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 0365cb776fb..e03f60ac040 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -292,6 +292,7 @@ character-set=latin7 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 7a8ff9d3c8c..b3591e2f4ab 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -287,6 +287,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index e465cb3f899..6a404b2083f 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -299,6 +299,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 6bbcae1bca0..47cb5125dbb 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -287,6 +287,7 @@ character-set=greek "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 73203da9826..cbe34d19fe1 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -289,6 +289,7 @@ character-set=latin2 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index a99e381521e..6f7aaaec669 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -287,6 +287,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index fb85ae593d3..ee9a546cb11 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -289,6 +289,7 @@ character-set=ujis "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 50415a9b051..6aa94a4482a 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -287,6 +287,7 @@ character-set=euckr "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 9409c82e06e..65faac4365c 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -289,6 +289,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index f14abb40111..26d0bae406f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -289,6 +289,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index dcf2369f727..55e3d9dc1dc 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -291,6 +291,7 @@ character-set=latin2 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index ea002431020..519434c24b5 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -288,6 +288,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 8f279b86731..5c6ecd8ddd7 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -291,6 +291,7 @@ character-set=latin2 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index b4e33c2e26e..6f0dd2d9ac7 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -289,6 +289,7 @@ character-set=koi8r "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 074714047de..e9be8102e0e 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -282,6 +282,7 @@ character-set=cp1250 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 39aca7893a9..af3eae4f97b 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -295,6 +295,7 @@ character-set=latin2 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 465fc98d60f..b799ce54bec 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -289,6 +289,7 @@ character-set=latin1 "Query cache failed to set size %lu, new query cache size is %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index a1e06d2bde7..40fc31dfdb3 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -287,6 +287,7 @@ character-set=latin1 "Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu", "Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index ddf632e0dbd..e0d42d6264b 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -292,6 +292,7 @@ character-set=koi8u "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu", "Column '%-.64s' cannot be part of FULLTEXT index", "Unknown key cache '%-.100s'", +"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/slave.cc b/sql/slave.cc index c531d3cc4f7..695e0b2c2c4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1367,32 +1367,9 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname) } /* - The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. It is - notable that the last kilobytes of it (8 kB for example) may live in - memory, not on disk (depending on what the thread using it does). While - this is efficient, it has a side-effect one must know: - The size of the relay log on disk (displayed by 'ls -l' on Unix) can be a - few kilobytes less than one would expect by doing SHOW SLAVE STATUS; this - happens when only the IO thread is started (not the SQL thread). The - "missing" kilobytes are in memory, are preserved during 'STOP SLAVE; START - SLAVE IO_THREAD', and are flushed to disk when the slave's mysqld stops. So - this does not cause any bug. Example of how disk size grows by leaps: - - Read_Master_Log_Pos: 7811 -rw-rw---- 1 guilhem qq 4 Jun 5 16:19 gbichot2-relay-bin.002 - ...later... - Read_Master_Log_Pos: 9744 -rw-rw---- 1 guilhem qq 8192 Jun 5 16:27 gbichot2-relay-bin.002 - - See how 4 is less than 7811 and 8192 is less than 9744. - - WARNING: this is risky because the slave can stay like this for a long - time; then if it has a power failure, master.info says the I/O thread has - read until 9744 while the relay-log contains only until 8192 (the - in-memory part from 8192 to 9744 has been lost), so the SQL slave thread - will miss some events, silently breaking replication. - Ideally we would like to flush master.info only when we know that the relay - log has no in-memory tail. - Note that the above problem may arise only when only the IO thread is - started, which is unlikely. + The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. + Note that the I/O thread flushes it to disk after writing every event, in + flush_master_info(mi, 1). */ /* @@ -1578,7 +1555,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) save_proc_info= thd->enter_cond(&rli->log_space_cond, &rli->log_space_lock, "\ -Waiting for the SQL slave thread to free enough relay log space"); +Waiting for the slave SQL thread to free enough relay log space"); while (rli->log_space_limit < rli->log_space_total && !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) @@ -1849,7 +1826,7 @@ file '%s')", fname); mi->inited = 1; // now change cache READ -> WRITE - must do this before flush_master_info reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1); - if ((error=test(flush_master_info(mi)))) + if ((error=test(flush_master_info(mi, 1)))) sql_print_error("Failed to flush master info file"); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); @@ -1964,7 +1941,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi) sizeof(mi->user))); field_list.push_back(new Item_return_int("Master_Port", 7, MYSQL_TYPE_LONG)); - field_list.push_back(new Item_return_int("Connect_retry", 10, + field_list.push_back(new Item_return_int("Connect_Retry", 10, MYSQL_TYPE_LONG)); field_list.push_back(new Item_empty_string("Master_Log_File", FN_REFLEN)); @@ -1978,24 +1955,24 @@ int show_master_info(THD* thd, MASTER_INFO* mi) FN_REFLEN)); field_list.push_back(new Item_empty_string("Slave_IO_Running", 3)); field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3)); - field_list.push_back(new Item_empty_string("Replicate_do_db", 20)); - field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20)); - field_list.push_back(new Item_empty_string("Replicate_do_table", 20)); - field_list.push_back(new Item_empty_string("Replicate_ignore_table", 23)); - field_list.push_back(new Item_empty_string("Replicate_wild_do_table", 24)); - field_list.push_back(new Item_empty_string("Replicate_wild_ignore_table", + field_list.push_back(new Item_empty_string("Replicate_Do_DB", 20)); + field_list.push_back(new Item_empty_string("Replicate_Ignore_DB", 20)); + field_list.push_back(new Item_empty_string("Replicate_Do_Table", 20)); + field_list.push_back(new Item_empty_string("Replicate_Ignore_Table", 23)); + field_list.push_back(new Item_empty_string("Replicate_Wild_Do_Table", 24)); + field_list.push_back(new Item_empty_string("Replicate_Wild_Ignore_Table", 28)); - field_list.push_back(new Item_return_int("Last_errno", 4, MYSQL_TYPE_LONG)); - field_list.push_back(new Item_empty_string("Last_error", 20)); - field_list.push_back(new Item_return_int("Skip_counter", 10, + field_list.push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG)); + field_list.push_back(new Item_empty_string("Last_Error", 20)); + field_list.push_back(new Item_return_int("Skip_Counter", 10, MYSQL_TYPE_LONG)); - field_list.push_back(new Item_return_int("Exec_master_log_pos", 10, + field_list.push_back(new Item_return_int("Exec_Master_Log_Pos", 10, MYSQL_TYPE_LONGLONG)); - field_list.push_back(new Item_return_int("Relay_log_space", 10, + field_list.push_back(new Item_return_int("Relay_Log_Space", 10, MYSQL_TYPE_LONGLONG)); - field_list.push_back(new Item_empty_string("Until_condition", 6)); + field_list.push_back(new Item_empty_string("Until_Condition", 6)); field_list.push_back(new Item_empty_string("Until_Log_File", FN_REFLEN)); - field_list.push_back(new Item_return_int("Until_Log_pos", 10, + field_list.push_back(new Item_return_int("Until_Log_Pos", 10, MYSQL_TYPE_LONGLONG)); field_list.push_back(new Item_empty_string("Master_SSL_Allowed", 7)); field_list.push_back(new Item_empty_string("Master_SSL_CA_File", @@ -2008,7 +1985,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi) sizeof(mi->ssl_cipher))); field_list.push_back(new Item_empty_string("Master_SSL_Key", sizeof(mi->ssl_key))); - field_list.push_back(new Item_return_int("Seconds_behind_master", 10, + field_list.push_back(new Item_return_int("Seconds_Behind_Master", 10, MYSQL_TYPE_LONGLONG)); if (protocol->send_fields(&field_list, 1)) @@ -2099,7 +2076,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi) } -bool flush_master_info(MASTER_INFO* mi) +bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) { IO_CACHE* file = &mi->file; char lbuf[22]; @@ -2107,6 +2084,30 @@ bool flush_master_info(MASTER_INFO* mi) DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos)); /* + Flush the relay log to disk. If we don't do it, then the relay log while + have some part (its last kilobytes) in memory only, so if the slave server + dies now, with, say, from master's position 100 to 150 in memory only (not + on disk), and with position 150 in master.info, then when the slave + restarts, the I/O thread will fetch binlogs from 150, so in the relay log + we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the + SQL thread will jump from 100 to 150, and replication will silently break. + + When we come to this place in code, relay log may or not be initialized; + the caller is responsible for setting 'flush_relay_log_cache' accordingly. + */ + if (flush_relay_log_cache) + flush_io_cache(mi->rli.relay_log.get_log_file()); + + /* + We flushed the relay log BEFORE the master.info file, because if we crash + now, we will get a duplicate event in the relay log at restart. If we + flushed in the other order, we would get a hole in the relay log. + And duplicate is better than hole (with a duplicate, in later versions we + can add detection and scrap one event; with a hole there's nothing we can + do). + */ + + /* In certain cases this code may create master.info files that seems corrupted, because of extra lines filled with garbage in the end file (this happens if new contents take less space than previous @@ -2290,7 +2291,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, DBUG_PRINT("info",("Waiting for master update")); const char* msg = thd->enter_cond(&data_cond, &data_lock, - "Waiting for the SQL slave thread to \ + "Waiting for the slave SQL thread to \ advance position"); /* We are going to pthread_cond_(timed)wait(); if the SQL thread stops it @@ -2361,7 +2362,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) | OPTION_AUTO_IS_NULL; /* - It's nonsense to constraint the slave threads with max_join_size; if a + It's nonsense to constrain the slave threads with max_join_size; if a query succeeded on master, we HAVE to execute it. */ thd->variables.max_join_size= HA_POS_ERROR; @@ -2981,7 +2982,7 @@ reconnect done to recover from failed read"); sql_print_error("Slave I/O thread could not queue event from master"); goto err; } - flush_master_info(mi); + flush_master_info(mi, 1); /* sure that we can flush the relay log */ /* See if the relay logs take too much space. We don't lock mi->rli.log_space_lock here; this dirty read saves time @@ -3121,9 +3122,10 @@ slave_begin: Reset errors for a clean start (otherwise, if the master is idle, the SQL thread may execute no Query_log_event, so the error will remain even though there's no problem anymore). Do not reset the master timestamp - (imagine the slave has caught everything, the STOP SLAVE and START SLAVE: as - we are not sure that we are going to receive a query, we want to remember - the last master timestamp (to say how many seconds behind we are now. + (imagine the slave has caught everything, the STOP SLAVE and START SLAVE: + as we are not sure that we are going to receive a query, we want to + remember the last master timestamp (to say how many seconds behind we are + now. But the master timestamp is reset by RESET SLAVE & CHANGE MASTER. */ clear_slave_error(rli); @@ -3796,8 +3798,6 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) error=1; if (flush_io_cache(file)) error=1; - if (flush_io_cache(rli->cur_log)) // QQ Why this call ? - error=1; return error; } diff --git a/sql/slave.h b/sql/slave.h index f8093826f58..e42b93a47ef 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -461,7 +461,7 @@ typedef struct st_table_rule_ent int init_slave(); void init_slave_skip_errors(const char* arg); -bool flush_master_info(MASTER_INFO* mi); +bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); bool flush_relay_log_info(RELAY_LOG_INFO* rli); int register_slave_on_master(MYSQL* mysql); int terminate_slave_threads(MASTER_INFO* mi, int thread_mask, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 78a92193b5d..f4048fd9775 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -139,6 +139,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) READ_RECORD read_record_info; MYSQL_LOCK *lock; my_bool return_val=1; + bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; + DBUG_ENTER("acl_init"); if (!acl_cache) @@ -198,6 +200,13 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) host.access= get_access(table,2); host.access= fix_rights_for_db(host.access); host.sort= get_sort(2,host.host.hostname,host.db); + if (check_no_resolve && hostname_requires_resolving(host.host.hostname)) + { + sql_print_error("Warning: 'host' entry '%s|%s' " + "ignored in --skip-name-resolve mode.", + host.host.hostname, host.db, host.host.hostname); + continue; + } #ifndef TO_BE_REMOVED if (table->fields == 8) { // Without grant @@ -259,6 +268,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ACL_USER user; update_hostname(&user.host, get_field(&mem, table->field[0])); user.user= get_field(&mem, table->field[1]); + if (check_no_resolve && hostname_requires_resolving(user.host.hostname)) + { + sql_print_error("Warning: 'user' entry '%s@%s' " + "ignored in --skip-name-resolve mode.", + user.user, user.host.hostname, user.host.hostname); + continue; + } + const char *password= get_field(&mem, table->field[2]); uint password_len= password ? strlen(password) : 0; set_user_salt(&user, password, password_len); @@ -353,6 +370,13 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) continue; } db.user=get_field(&mem, table->field[2]); + if (check_no_resolve && hostname_requires_resolving(db.host.hostname)) + { + sql_print_error("Warning: 'db' entry '%s %s@%s' " + "ignored in --skip-name-resolve mode.", + db.db, db.user, db.host.hostname, db.host.hostname); + continue; + } db.access=get_access(table,3); db.access=fix_rights_for_db(db.access); db.sort=get_sort(3,db.host.hostname,db.db,db.user); @@ -632,8 +656,8 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, if (acl_user) { /* OK. User found and password checked continue validation */ - Vio *vio=thd->net.vio; #ifdef HAVE_OPENSSL + Vio *vio=thd->net.vio; SSL *ssl= (SSL*) vio->ssl_arg; #endif @@ -1256,6 +1280,25 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, (ip && !wild_compare(ip,host->hostname,0))); } +bool hostname_requires_resolving(const char *hostname) +{ + char cur; + if (!hostname) + return false; + int namelen= strlen(hostname); + int lhlen= strlen(my_localhost); + if ((namelen == lhlen) && + !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen, + (const uchar *)my_localhost, strlen(my_localhost))) + return false; + for (; (cur=*hostname); hostname++) + { + if ((cur != '%') && (cur != '_') && (cur != '.') && + ((cur < '0') || (cur > '9'))) + return true; + } + return false; +} /* Update grants in the user and database privilege tables @@ -2443,6 +2486,7 @@ my_bool grant_init(THD *org_thd) MYSQL_LOCK *lock; my_bool return_val= 1; TABLE *t_table, *c_table; + bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; DBUG_ENTER("grant_init"); grant_option = FALSE; @@ -2492,13 +2536,31 @@ my_bool grant_init(THD *org_thd) do { GRANT_TABLE *mem_check; - if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || - mem_check->ok() && my_hash_insert(&column_priv_hash,(byte*) mem_check)) + if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || mem_check->ok()) { /* This could only happen if we are out memory */ grant_option= FALSE; /* purecov: deadcode */ goto end_unlock; } + + if (check_no_resolve) + { + if (hostname_requires_resolving(mem_check->host)) + { + char buff[MAX_FIELD_WIDTH]; + sql_print_error("Warning: 'tables_priv' entry '%s %s@%s' " + "ignored in --skip-name-resolve mode.", + mem_check->tname, mem_check->user, + mem_check->host, mem_check->host); + continue; + } + } + + if (my_hash_insert(&column_priv_hash,(byte*) mem_check)) + { + grant_option= FALSE; + goto end_unlock; + } } while (!t_table->file->index_next(t_table->record[0])); @@ -3456,7 +3518,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) { uint counter; int result; - ACL_USER *acl_user; ACL_DB *acl_db; + ACL_DB *acl_db; TABLE_LIST tables[4]; DBUG_ENTER("mysql_revoke_all"); @@ -3470,7 +3532,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) List_iterator <LEX_USER> user_list(list); while ((lex_user=user_list++)) { - if (!(acl_user= check_acl_user(lex_user, &counter))) + if (!check_acl_user(lex_user, &counter)) { sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists", lex_user->user.str, diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 7e96f2eaff1..8b8115b10db 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -131,6 +131,7 @@ public: /* prototypes */ +bool hostname_requires_resolving(const char *hostname); my_bool acl_init(THD *thd, bool dont_read_acl_tables); void acl_reload(THD *thd); void acl_free(bool end=0); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index abaa77a4b4d..5b347267adb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -35,7 +35,6 @@ HASH assign_cache; static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, const char *name, const char *alias); static void free_cache_entry(TABLE *entry); -static void free_assign_entry(KEY_CACHE_ASMT *key_cache_asmt); static void mysql_rm_tmp_tables(void); @@ -1933,7 +1932,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, } } else if (!table_name && (item->eq(find,0) || - find->name && + find->name && item->name && !my_strcasecmp(system_charset_info, item->name,find->name))) { @@ -2024,20 +2023,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, DBUG_RETURN(test(thd->net.report_error)); } -/* - Mark all items in list as not fixed (0 assigned to 'fixed' field) - - SYNOPSYS - unfix_item_list() - item_list - list of items -*/ -void unfix_item_list(List<Item> item_list) -{ - Item *item; - List_iterator_fast<Item> it(item_list); - while ((item= it++)) - item->walk(&Item::remove_fixed, 0); -} /* Remap table numbers if INSERT ... SELECT diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index e5e50c180bf..0274cd700da 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -29,7 +29,7 @@ template <uint default_width> class Bitmap public: Bitmap() { init(); } Bitmap(Bitmap& from) { *this=from; } - Bitmap(uint prefix_to_set) { init(prefix_to_set); } + explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); } void init() { bitmap_init(&map, buffer, default_width, 0); } void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); } uint length() const { return default_width; } @@ -91,7 +91,7 @@ template <> class Bitmap<64> ulonglong map; public: Bitmap<64>() { } - Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); } + explicit Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); } void init() { } void init(uint prefix_to_set) { set_prefix(prefix_to_set); } uint length() const { return 64; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e2d1069975b..39305a724bb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -94,8 +94,8 @@ THD::THD():user_time(0), is_fatal_error(0), lex= &main_lex; host=user=priv_user=db=query=ip=0; host_or_ip= "connecting host"; - locked=some_tables_deleted=no_errors=password= - query_start_used=prepare_command=0; + locked=some_tables_deleted=no_errors=password= 0; + query_start_used= 0; count_cuted_fields= CHECK_FIELD_IGNORE; killed= NOT_KILLED; db_length=query_length=col_access=0; @@ -1047,9 +1047,9 @@ bool select_dump::send_eof() return error; } -select_subselect::select_subselect(Item_subselect *item) +select_subselect::select_subselect(Item_subselect *item_arg) { - this->item=item; + item= item_arg; } bool select_singlerow_subselect::send_data(List<Item> &items) @@ -1269,3 +1269,14 @@ bool select_dumpvar::send_eof() ::send_ok(thd,row_count); return 0; } + +/**************************************************************************** + TMP_TABLE_PARAM +****************************************************************************/ + +void TMP_TABLE_PARAM::init() +{ + field_count= sum_func_count= func_count= hidden_field_count= 0; + group_parts= group_length= group_null_parts= 0; + quick_group= 1; +} diff --git a/sql/sql_class.h b/sql/sql_class.h index f9d74f8b4da..457c77a3a04 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -619,7 +619,6 @@ public: my_error(killed_errno(), MYF(0)); } - bool prepare_command; bool tmp_table_used; bool charset_is_system_charset, charset_is_collation_connection; bool slow_command; @@ -913,7 +912,12 @@ public: class TMP_TABLE_PARAM :public Sql_alloc { - public: +private: + /* Prevent use of these (not safe because of lists and copy_field) */ + TMP_TABLE_PARAM(const TMP_TABLE_PARAM &); + void operator=(TMP_TABLE_PARAM &); + +public: List<Item> copy_funcs; List<Item> save_copy_funcs; List_iterator_fast<Item> copy_funcs_it; @@ -938,6 +942,7 @@ class TMP_TABLE_PARAM :public Sql_alloc { cleanup(); } + void init(void); inline void cleanup(void) { if (copy_field) /* Fix for Intel compiler */ @@ -963,6 +968,7 @@ class select_union :public select_result { bool send_data(List<Item> &items); bool send_eof(); bool flush(); + void set_table(TABLE *tbl) { table= tbl; } }; /* Base subselect interface class */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 22c6cc1f6f7..a057e0be967 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -264,7 +264,6 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) char path[FN_REFLEN+16]; long result=1; int error = 0; - uint create_options = create_info ? create_info->options : 0; DBUG_ENTER("mysql_alter_db"); VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -438,7 +437,6 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, char filePath[FN_REFLEN]; TABLE_LIST *tot_list=0, **tot_list_next; List<String> raid_dirs; - DBUG_ENTER("mysql_rm_known_files"); DBUG_PRINT("enter",("path: %s", org_path)); @@ -514,17 +512,24 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, deleted++; } } + List_iterator<String> it(raid_dirs); + String *dir; + if (thd->killed || (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1))) { + /* Free memory for allocated raid dirs */ + while ((dir= it++)) + delete dir; my_dirend(dirp); DBUG_RETURN(-1); } - List_iterator<String> it(raid_dirs); - String *dir; while ((dir= it++)) + { if (rmdir(dir->c_ptr()) < 0) found_other_files++; + delete dir; + } my_dirend(dirp); /* diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 719686a56c3..e8f1c5d87de 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -62,16 +62,14 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *org_table_list) { - SELECT_LEX *select_cursor= unit->first_select(); - List<Item> item_list; + SELECT_LEX *first_select= unit->first_select(); TABLE *table; int res; select_union *derived_result; - TABLE_LIST *tables= (TABLE_LIST *)select_cursor->table_list.first; - TMP_TABLE_PARAM tmp_table_param; - bool is_union= select_cursor->next_select() && - select_cursor->next_select()->linkage == UNION_TYPE; - bool is_subsel= select_cursor->first_inner_unit() ? 1: 0; + TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first; + bool is_union= first_select->next_select() && + first_select->next_select()->linkage == UNION_TYPE; + bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); @@ -112,16 +110,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, fix_tables_pointers(unit); } - lex->current_select= select_cursor; - TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; - /* Setting up. A must if a join or IGNORE, USE or similar are utilised */ - if (setup_tables(first_table) || - setup_wild(thd, first_table, select_cursor->item_list, 0, - select_cursor->with_wild)) - { - res= -1; + if (!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory + + // st_select_lex_unit::prepare correctly work for single select + if ((res= unit->prepare(thd, derived_result))) goto exit; - } /* This is done in order to redo all field optimisations when any of the @@ -133,30 +127,16 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, cursor->table->clear_query_id= 1; } - item_list= select_cursor->item_list; - select_cursor->with_wild= 0; - if (select_cursor->setup_ref_array(thd, - select_cursor->order_list.elements + - select_cursor->group_list.elements) || - setup_fields(thd, select_cursor->ref_pointer_array, first_table, - item_list, 0, 0, 1)) - { - res= -1; - goto exit; - } - // Item list should be fix_fielded yet another time in JOIN::prepare - unfix_item_list(item_list); - - bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); - tmp_table_param.field_count= item_list.elements; + derived_result->tmp_table_param.init(); + derived_result->tmp_table_param.field_count= unit->types.elements; /* Temp table is created so that it hounours if UNION without ALL is to be processed */ - if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, - (ORDER*) 0, + if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, + unit->types, (ORDER*) 0, is_union && !unit->union_option, 1, - (select_cursor->options | thd->options | + (first_select->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, org_table_list->alias))) @@ -164,70 +144,67 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, res= -1; goto exit; } - - if ((derived_result=new select_union(table))) + derived_result->set_table(table); + + unit->offset_limit_cnt= first_select->offset_limit; + unit->select_limit_cnt= first_select->select_limit+ + first_select->offset_limit; + if (unit->select_limit_cnt < first_select->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; + if (unit->select_limit_cnt == HA_POS_ERROR) + first_select->options&= ~OPTION_FOUND_ROWS; + + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + + if (!res) { - derived_result->tmp_table_param=tmp_table_param; - unit->offset_limit_cnt= select_cursor->offset_limit; - unit->select_limit_cnt= select_cursor->select_limit+ - select_cursor->offset_limit; - if (unit->select_limit_cnt < select_cursor->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; - if (unit->select_limit_cnt == HA_POS_ERROR) - select_cursor->options&= ~OPTION_FOUND_ROWS; - - if (is_union) - res= mysql_union(thd, lex, derived_result, unit, 1); + /* + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables + */ + if (derived_result->flush()) + res= 1; else - res= mysql_select(thd, &select_cursor->ref_pointer_array, - (TABLE_LIST*) select_cursor->table_list.first, - select_cursor->with_wild, - select_cursor->item_list, select_cursor->where, - (select_cursor->order_list.elements+ - select_cursor->group_list.elements), - (ORDER *) select_cursor->order_list.first, - (ORDER *) select_cursor->group_list.first, - select_cursor->having, (ORDER*) NULL, - (select_cursor->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, select_cursor, 1); - - if (!res) { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else - { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= select_cursor->select_number; - table->tmp_table= TMP_TABLE; + org_table_list->real_name=table->real_name; + org_table_list->table=table; + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + org_table_list->grant.privilege= SELECT_ACL; #endif - if (lex->describe) + if (lex->describe) + { + // to fix a problem in EXPLAIN + if (tables) { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } + for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) + if (cursor->table_list) + cursor->table_list->table=cursor->table; } - else - unit->exclude_tree(); - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); } + else + unit->exclude_tree(); + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } - delete derived_result; } + if (res) free_tmp_table(thd, table); else @@ -238,6 +215,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, } exit: + delete derived_result; lex->current_select= save_current_select; close_thread_tables(thd, 0, 1); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 3676f4644d2..c94d5e52bcf 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -102,6 +102,7 @@ void mysql_reset_errors(THD *thd) MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *msg) { + DBUG_ENTER("push_warning"); if (thd->query_id != thd->warn_id) mysql_reset_errors(thd); @@ -122,7 +123,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, } thd->warn_count[(uint) level]++; thd->total_warn_count++; - return err; + DBUG_RETURN(err); } /* diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 78e8c877c45..405cfdb5bdc 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -253,7 +253,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, continue; if (num_rows >= offset_limit) { - String *packet = &thd->packet; Item *item; protocol->prepare_for_resend(); it.rewind(); @@ -298,7 +297,20 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db, !my_strcasecmp(system_charset_info, (is_alias ? table->table_name : table->real_name), table_name)) + { + if (table->version != refresh_version) + { + VOID(pthread_mutex_lock(&LOCK_open)); + if (close_thread_table(thd, ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + VOID(pthread_cond_broadcast(&COND_refresh)); + } + VOID(pthread_mutex_unlock(&LOCK_open)); + continue; + } break; + } ptr= &(table->next); } return ptr; diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 6af4ffde0e1..c40133c04a8 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -524,7 +524,7 @@ int send_header_2(Protocol *protocol, bool for_category) same as strcmp */ -int string_ptr_cmp(const void* ptr1, const void* ptr2) +extern "C" int string_ptr_cmp(const void* ptr1, const void* ptr2) { String *str1= *(String**)ptr1; String *str2= *(String**)ptr2; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 28324de11da..67afc355153 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1467,6 +1467,8 @@ void select_insert::send_error(uint errcode,const char *err) bool select_insert::send_eof() { int error,error2; + DBUG_ENTER("select_insert::send_eof"); + if (!(error=table->file->extra(HA_EXTRA_NO_CACHE))) error=table->file->activate_all_index(thd); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -1499,20 +1501,18 @@ bool select_insert::send_eof() table->file->print_error(error,MYF(0)); //TODO error should be sent at the query processing end ::send_error(thd); - return 1; + DBUG_RETURN(1); } + + char buff[160]; + if (info.handle_duplicates == DUP_IGNORE) + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, + (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); else - { - char buff[160]; - if (info.handle_duplicates == DUP_IGNORE) - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); - else - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) info.deleted, (ulong) thd->cuted_fields); - ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff); - return 0; - } + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, + (ulong) info.deleted, (ulong) thd->cuted_fields); + ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff); + DBUG_RETURN(0); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6ed8d23ab95..a67ee2385b9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -454,7 +454,7 @@ int yylex(void *arg, void *yythd) reg1 uchar c; int tokval, result_state; uint length; - enum my_lex_states state,prev_state; + enum my_lex_states state; LEX *lex= (((THD *)yythd)->lex); YYSTYPE *yylval=(YYSTYPE*) arg; CHARSET_INFO *cs= ((THD *) yythd)->charset(); @@ -463,7 +463,7 @@ int yylex(void *arg, void *yythd) lex->yylval=yylval; // The global state lex->tok_start=lex->tok_end=lex->ptr; - prev_state=state=lex->next_state; + state=lex->next_state; lex->next_state=MY_LEX_OPERATOR_OR_IDENT; LINT_INIT(c); for (;;) @@ -1197,7 +1197,7 @@ void st_select_lex_unit::exclude_level() */ void st_select_lex_unit::exclude_tree() { - SELECT_LEX_UNIT *units= 0, **units_last= &units; + SELECT_LEX_UNIT *units= 0; for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { // unlink current level from global SELECTs list @@ -1292,28 +1292,6 @@ bool st_select_lex::test_limit() return(0); } - - - - - - - - - - - - - - - - - - - - - - /* Interface method of table list creation for query @@ -1333,18 +1311,14 @@ bool st_select_lex::test_limit() 0 - OK !0 - error */ -bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex, - TABLE_LIST **result, +bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex, + TABLE_LIST **result_arg, bool check_derived) { - *result= 0; - for (SELECT_LEX_UNIT *unit= this; unit; unit= unit->next_unit()) - { - if ((res= unit->create_total_list_n_last_return(thd, lex, &result, - check_derived))) - return res; - } - return 0; + *result_arg= 0; + res= create_total_list_n_last_return(thd_arg, lex, &result_arg, + check_derived); + return res; } /* @@ -1367,12 +1341,14 @@ bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex, 0 - OK !0 - error */ -bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, - TABLE_LIST ***result, - bool check_derived) +bool st_select_lex_unit:: +create_total_list_n_last_return(THD *thd_arg, + st_lex *lex, + TABLE_LIST ***result_arg, + bool check_derived) { TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; - TABLE_LIST **new_table_list= *result, *aux; + TABLE_LIST **new_table_list= *result_arg, *aux; SELECT_LEX *sl= (SELECT_LEX*)slave; /* @@ -1391,7 +1367,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, if (sl->order_list.first && sl->next_select() && !sl->braces && sl->linkage != GLOBAL_OPTIONS_TYPE) { - net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY"); + net_printf(thd_arg,ER_WRONG_USAGE,"UNION","ORDER BY"); return 1; } @@ -1409,12 +1385,12 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, if ((aux= (TABLE_LIST*) sl->table_list.first)) { - TABLE_LIST *next; - for (; aux; aux= next) + TABLE_LIST *next_table; + for (; aux; aux= next_table) { TABLE_LIST *cursor; - next= aux->next; - for (cursor= **result; cursor; cursor= cursor->next) + next_table= aux->next; + for (cursor= **result_arg; cursor; cursor= cursor->next) if (!strcmp(cursor->db, aux->db) && !strcmp(cursor->real_name, aux->real_name) && !strcmp(cursor->alias, aux->alias)) @@ -1446,7 +1422,7 @@ end: *new_table_list= slave_list_first; new_table_list= slave_list_last; } - *result= new_table_list; + *result_arg= new_table_list; return 0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8f879f12b10..4199bb18548 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -306,7 +306,6 @@ class JOIN; class select_union; class st_select_lex_unit: public st_select_lex_node { protected: - List<Item> item_list; TABLE_LIST result_table_list; select_union *union_result; TABLE *table; /* temporary table using for appending UNION results */ @@ -316,9 +315,19 @@ protected: ulong found_rows_for_union; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed, // already executed - t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods + executed; // already executed + public: + // list of fields which points to temporary table for union + List<Item> item_list; + /* + list of types of items inside union (used for union & derived tables) + + Item_type_holders from which this list consist may have pointers to Field, + pointers is valid only after preparing SELECTS of this unit and before + any SELECT of this unit execution + */ + List<Item> types; /* Pointer to 'last' select or pointer to unit where stored global parameters for union @@ -353,7 +362,7 @@ public: void exclude_tree(); /* UNION methods */ - int prepare(THD *thd, select_result *result, bool tables_and_fields_initied); + int prepare(THD *thd, select_result *result); int exec(); int cleanup(); diff --git a/sql/sql_list.h b/sql/sql_list.h index 2f0425f1ddc..592173c36da 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -290,9 +290,9 @@ public: List_iterator_fast(List<T> &a) : base_list_iterator(a) {} inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline void rewind(void) { base_list_iterator::rewind(); } - void sublist(List<T> &list, uint el) + void sublist(List<T> &list_arg, uint el_arg) { - base_list_iterator::sublist(list, el); + base_list_iterator::sublist(list_arg, el_arg); } }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 17ab42f979e..14d686a5613 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -140,7 +140,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, USER_RESOURCES *mqh) { int return_val=0; - uint temp_len, user_len, host_len; + uint temp_len, user_len; char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2]; struct user_conn *uc; @@ -148,7 +148,6 @@ static int get_or_create_user_conn(THD *thd, const char *user, DBUG_ASSERT(host != 0); user_len=strlen(user); - host_len=strlen(host); temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; (void) pthread_mutex_lock(&LOCK_user_conn); if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, @@ -2734,7 +2733,7 @@ mysql_execute_command(THD *thd) (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, - result, unit, select_lex, 0); + result, unit, select_lex); if (thd->net.report_error) res= -1; delete result; @@ -3196,6 +3195,19 @@ mysql_execute_command(THD *thd) } } } + if (specialflag & SPECIAL_NO_RESOLVE) + { + LEX_USER *user; + List_iterator <LEX_USER> user_list(lex->users_list); + while ((user=user_list++)) + { + if (hostname_requires_resolving(user->host.str)) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_HOSTNAME_WONT_WORK, + ER(ER_WARN_HOSTNAME_WONT_WORK), + user->host.str); + } + } if (tables) { if (grant_option && check_grant(thd, @@ -4593,8 +4605,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, LEX_STRING *alias, ulong table_options, thr_lock_type lock_type, - List<String> *use_index, - List<String> *ignore_index, + List<String> *use_index_arg, + List<String> *ignore_index_arg, LEX_STRING *option) { register TABLE_LIST *ptr; @@ -4650,12 +4662,12 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; - if (use_index) - ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, - sizeof(*use_index)); - if (ignore_index) - ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index, - sizeof(*ignore_index)); + if (use_index_arg) + ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg, + sizeof(*use_index_arg)); + if (ignore_index_arg) + ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index_arg, + sizeof(*ignore_index_arg)); ptr->option= option ? option->str : 0; /* check that used name is unique */ if (lock_type != TL_IGNORE) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f09a8b32470..7715ab01044 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -427,8 +427,10 @@ static bool insert_params_withlog(PREP_STMT *stmt, uchar *pos, uchar *read_pos) Item_param *param; DBUG_ENTER("insert_params_withlog"); - String str, *res, *query= new String(stmt->query->alloced_length()); - query->copy(*stmt->query); + String str, query, *res; + + if (query.copy(*stmt->query)) + DBUG_RETURN(1); ulong param_no= 0; uint32 length= 0; @@ -452,16 +454,14 @@ static bool insert_params_withlog(PREP_STMT *stmt, uchar *pos, uchar *read_pos) res= param->query_val_str(&str); } } - if (query->replace(param->pos_in_query+length, 1, *res)) + if (query.replace(param->pos_in_query+length, 1, *res)) DBUG_RETURN(1); length+= res->length()-1; param_no++; } - if (alloc_query(stmt->thd, (char *)query->ptr(), query->length()+1)) + if (alloc_query(thd, (char *)query.ptr(), query.length()+1)) DBUG_RETURN(1); - - query->free(); DBUG_RETURN(0); } @@ -683,7 +683,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, if (join->prepare(&select_lex->ref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc, - select_lex, unit, 0)) + select_lex, unit)) DBUG_RETURN(1); if (send_prep_stmt(stmt, fields.elements) || thd->protocol_simple.send_fields(&fields, 0) || @@ -786,7 +786,6 @@ static bool parse_prepare_query(PREP_STMT *stmt, mysql_init_query(thd); LEX *lex=lex_start(thd, (uchar*) packet, length); lex->safe_to_cache_query= 0; - thd->prepare_command= TRUE; thd->lex->param_count= 0; if (!yyparse((void *)thd) && !thd->is_fatal_error) error= send_prepare_results(stmt); @@ -1067,10 +1066,9 @@ void mysql_stmt_reset(THD *thd, char *packet) void mysql_stmt_free(THD *thd, char *packet) { ulong stmt_id= uint4korr(packet); - PREP_STMT *stmt; DBUG_ENTER("mysql_stmt_free"); - if (!(stmt=find_prepared_statement(thd, stmt_id, "close"))) + if (!find_prepared_statement(thd, stmt_id, "close")) { send_error(thd); // Not seen by the client DBUG_VOID_RETURN; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index cc64ca1aa2b..c0ee4277128 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -961,8 +961,8 @@ void kill_zombie_dump_threads(uint32 slave_server_id) int change_master(THD* thd, MASTER_INFO* mi) { int thread_mask; - const char* errmsg=0; - bool need_relay_log_purge=1; + const char* errmsg= 0; + bool need_relay_log_purge= 1; DBUG_ENTER("change_master"); lock_slave_threads(mi); @@ -1055,7 +1055,41 @@ int change_master(THD* thd, MASTER_INFO* mi) mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos; } - flush_master_info(mi); + /* + If user did specify neither host nor port nor any log name nor any log + pos, i.e. he specified only user/password/master_connect_retry, he probably + wants replication to resume from where it had left, i.e. from the + coordinates of the **SQL** thread (imagine the case where the I/O is ahead + of the SQL; restarting from the coordinates of the I/O would lose some + events which is probably unwanted when you are just doing minor changes + like changing master_connect_retry). + A side-effect is that if only the I/O thread was started, this thread may + restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a + much more unlikely situation than the one we are fixing here). + Note: coordinates of the SQL thread must be read here, before the + 'if (need_relay_log_purge)' block which resets them. + */ + if (!lex_mi->host && !lex_mi->port && + !lex_mi->log_file_name && !lex_mi->pos && + need_relay_log_purge) + { + /* + Sometimes mi->rli.master_log_pos == 0 (it happens when the SQL thread is + not initialized), so we use a max(). + What happens to mi->rli.master_log_pos during the initialization stages + of replication is not 100% clear, so we guard against problems using + max(). + */ + mi->master_log_pos = max(BIN_LOG_HEADER_SIZE, + mi->rli.group_master_log_pos); + strmake(mi->master_log_name, mi->rli.group_master_log_name, + sizeof(mi->master_log_name)-1); + } + /* + Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never + a slave before). + */ + flush_master_info(mi, 0); if (need_relay_log_purge) { relay_log_purge= 1; @@ -1087,10 +1121,21 @@ int change_master(THD* thd, MASTER_INFO* mi) } mi->rli.group_master_log_pos = mi->master_log_pos; DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); - /* If changing RELAY_LOG_FILE or RELAY_LOG_POS, this will be nonsense: */ + + /* + Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block, + so restore them to good values. If we left them to ''/0, that would work; + but that would fail in the case of 2 successive CHANGE MASTER (without a + START SLAVE in between): because first one would set the coords in mi to + the good values of those in rli, the set those in rli to ''/0, then + second CHANGE MASTER would set the coords in mi to those of rli, i.e. to + ''/0: we have lost all copies of the original good coordinates. + That's why we always save good coords in rli. + */ mi->rli.group_master_log_pos= mi->master_log_pos; strmake(mi->rli.group_master_log_name,mi->master_log_name, sizeof(mi->rli.group_master_log_name)-1); + if (!mi->rli.group_master_log_name[0]) // uninitialized case mi->rli.group_master_log_pos=0; @@ -1251,8 +1296,8 @@ int show_binlog_info(THD* thd) field_list.push_back(new Item_empty_string("File", FN_REFLEN)); field_list.push_back(new Item_return_int("Position",20, MYSQL_TYPE_LONGLONG)); - field_list.push_back(new Item_empty_string("Binlog_do_db",255)); - field_list.push_back(new Item_empty_string("Binlog_ignore_db",255)); + field_list.push_back(new Item_empty_string("Binlog_Do_DB",255)); + field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",255)); if (protocol->send_fields(&field_list, 1)) DBUG_RETURN(-1); @@ -1291,9 +1336,7 @@ int show_binlogs(THD* thd) { IO_CACHE *index_file; char fname[FN_REFLEN]; - NET* net = &thd->net; List<Item> field_list; - String *packet = &thd->packet; uint length; Protocol *protocol= thd->protocol; DBUG_ENTER("show_binlogs"); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 662b288c7c2..d7c836fe516 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -178,7 +178,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) - res=mysql_union(thd, lex, result, &lex->unit, 0); + res=mysql_union(thd, lex, result, &lex->unit); else res= mysql_select(thd, &select_lex->ref_pointer_array, (TABLE_LIST*) select_lex->table_list.first, @@ -191,7 +191,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) select_lex->having, (ORDER*) lex->proc_list.first, select_lex->options | thd->options, - result, &(lex->unit), &(lex->select_lex), 0); + result, &(lex->unit), &(lex->select_lex)); /* Don't set res if it's -1 as we may want this later */ DBUG_PRINT("info",("res: %d report_error: %d", res, @@ -286,9 +286,8 @@ JOIN::prepare(Item ***rref_pointer_array, uint wild_num, COND *conds_init, uint og_num, ORDER *order_init, ORDER *group_init, Item *having_init, - ORDER *proc_param_init, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, - bool tables_and_fields_initied) + ORDER *proc_param_init, SELECT_LEX *select_lex_arg, + SELECT_LEX_UNIT *unit_arg) { DBUG_ENTER("JOIN::prepare"); @@ -298,16 +297,14 @@ JOIN::prepare(Item ***rref_pointer_array, having= having_init; proc_param= proc_param_init; tables_list= tables_init; - select_lex= select; + select_lex= select_lex_arg; select_lex->join= this; - union_part= (unit->first_select()->next_select() != 0); + union_part= (unit_arg->first_select()->next_select() != 0); /* Check that all tables, fields, conds and order are ok */ - if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) || - setup_wild(thd, tables_list, - fields_list, - &all_fields, wild_num))) || + if (setup_tables(tables_list) || + setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, &all_fields, 1) || @@ -374,14 +371,14 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); } } - TABLE_LIST *table; - for (table=tables_list ; table ; table=table->next) + TABLE_LIST *table_ptr; + for (table_ptr= tables_list ; table_ptr ; table_ptr= table_ptr->next) tables++; } { /* Caclulate the number of groups */ send_group_parts= 0; - for (ORDER *group= group_list ; group ; group= group->next) + for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next) send_group_parts++; } @@ -421,13 +418,13 @@ JOIN::prepare(Item ***rref_pointer_array, ref_pointer_array_size= all_fields.elements*sizeof(Item*); this->group= group_list != 0; row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR : - unit->select_limit_cnt); + unit_arg->select_limit_cnt); /* select_limit is used to decide if we are likely to scan the whole table */ - select_limit= unit->select_limit_cnt; + select_limit= unit_arg->select_limit_cnt; if (having || (select_options & OPTION_FOUND_ROWS)) select_limit= HA_POS_ERROR; - do_send_rows = (unit->select_limit_cnt) ? 1 : 0; - this->unit= unit; + do_send_rows = (unit_arg->select_limit_cnt) ? 1 : 0; + unit= unit_arg; #ifdef RESTRICTED_GROUP if (sum_func_count && !group_list && (func_count || field_count)) @@ -436,7 +433,7 @@ JOIN::prepare(Item ***rref_pointer_array, goto err; } #endif - if (!procedure && result->prepare(fields_list, unit)) + if (!procedure && result->prepare(fields_list, unit_arg)) goto err; /* purecov: inspected */ if (select_lex->olap == ROLLUP_TYPE && rollup_init()) @@ -612,20 +609,20 @@ JOIN::optimize() if (const_tables && !thd->locked_tables && !(select_options & SELECT_NO_UNLOCK)) { - TABLE **table, **end; - for (table=this->table, end=table + const_tables ; - table != end; - table++) + TABLE **curr_table, **end; + for (curr_table= table, end=curr_table + const_tables ; + curr_table != end; + curr_table++) { /* BDB tables require that we call index_end() before doing an unlock */ - if ((*table)->key_read) + if ((*curr_table)->key_read) { - (*table)->key_read=0; - (*table)->file->extra(HA_EXTRA_NO_KEYREAD); + (*curr_table)->key_read=0; + (*curr_table)->file->extra(HA_EXTRA_NO_KEYREAD); } - (*table)->file->index_end(); + (*curr_table)->file->index_end(); } - mysql_unlock_some_tables(thd, this->table, const_tables); + mysql_unlock_some_tables(thd, table, const_tables); } if (!conds && outer_join) { @@ -968,18 +965,18 @@ JOIN::optimize() if (exec_tmp_table1->distinct) { table_map used_tables= thd->used_tables; - JOIN_TAB *join_tab= this->join_tab+tables-1; + JOIN_TAB *last_join_tab= join_tab+tables-1; do { - if (used_tables & join_tab->table->map) + if (used_tables & last_join_tab->table->map) break; - join_tab->not_used_in_distinct=1; - } while (join_tab-- != this->join_tab); + last_join_tab->not_used_in_distinct=1; + } while (last_join_tab-- != join_tab); /* Optimize "select distinct b from t1 order by key_part_1 limit #" */ if (order && skip_sort_order) { /* Should always succeed */ - if (test_if_skip_sort_order(&this->join_tab[const_tables], + if (test_if_skip_sort_order(&join_tab[const_tables], order, unit->select_limit_cnt, 0)) order=0; } @@ -1398,26 +1395,27 @@ JOIN::exec() { // Some tables may have been const curr_join->tmp_having->update_used_tables(); - JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables]; - table_map used_tables= curr_join->const_table_map | table->table->map; + JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables]; + table_map used_tables= (curr_join->const_table_map | + curr_table->table->map); Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having, used_tables, used_tables); if (sort_table_cond) { - if (!table->select) - if (!(table->select= new SQL_SELECT)) + if (!curr_table->select) + if (!(curr_table->select= new SQL_SELECT)) DBUG_VOID_RETURN; - if (!table->select->cond) - table->select->cond= sort_table_cond; + if (!curr_table->select->cond) + curr_table->select->cond= sort_table_cond; else // This should never happen - if (!(table->select->cond= new Item_cond_and(table->select->cond, - sort_table_cond))) + if (!(curr_table->select->cond= + new Item_cond_and(curr_table->select->cond, sort_table_cond))) DBUG_VOID_RETURN; - table->select_cond=table->select->cond; - table->select_cond->top_level_item(); - DBUG_EXECUTE("where",print_where(table->select->cond, + curr_table->select_cond= curr_table->select->cond; + curr_table->select_cond->top_level_item(); + DBUG_EXECUTE("where",print_where(curr_table->select->cond, "select and having");); curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having, ~ (table_map) 0, @@ -1434,9 +1432,9 @@ JOIN::exec() We can abort sorting after thd->select_limit rows if we there is no WHERE clause for any tables after the sorted one. */ - JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables+1]; + JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1]; JOIN_TAB *end_table= &curr_join->join_tab[tables]; - for (; table < end_table ; table++) + for (; curr_table < end_table ; curr_table++) { /* table->keyuse is set in the case there was an original WHERE clause @@ -1444,7 +1442,8 @@ JOIN::exec() table->on_expr tells us that it was a LEFT JOIN and there will be at least one row generated from the table. */ - if (table->select_cond || (table->keyuse && !table->on_expr)) + if (curr_table->select_cond || + (curr_table->keyuse && !curr_table->on_expr)) { /* We have to sort all rows */ curr_join->select_limit= HA_POS_ERROR; @@ -1522,11 +1521,11 @@ JOIN::cleanup() delete select; delete_dynamic(&keyuse); delete procedure; - for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); - unit != 0; - unit= unit->next_unit()) + for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit(); + lex_unit != 0; + lex_unit= lex_unit->next_unit()) { - error|= unit->cleanup(); + error|= lex_unit->cleanup(); } DBUG_RETURN(error); } @@ -1538,7 +1537,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_options, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool tables_and_fields_initied) + SELECT_LEX *select_lex) { int err; bool free_join= 1; @@ -1548,26 +1547,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (select_lex->join != 0) { join= select_lex->join; - if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) + // is it single SELECT in derived table, called in derived table creation + if (select_lex->linkage != DERIVED_TABLE_TYPE || + (select_options & SELECT_DESCRIBE)) { - //here is EXPLAIN of subselect or derived table - join->result= result; - if (!join->procedure && result->prepare(join->fields_list, unit)) + if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) { - DBUG_RETURN(-1); + //here is EXPLAIN of subselect or derived table + join->result= result; + if (!join->procedure && result->prepare(join->fields_list, unit)) + { + DBUG_RETURN(-1); + } } - } - else - { - if (join->prepare(rref_pointer_array, tables, wild_num, - conds, og_num, order, group, having, proc_param, - select_lex, unit, tables_and_fields_initied)) + else { - goto err; + if (join->prepare(rref_pointer_array, tables, wild_num, + conds, og_num, order, group, having, proc_param, + select_lex, unit)) + { + goto err; + } } + free_join= 0; } join->select_options= select_options; - free_join= 0; } else { @@ -1576,7 +1580,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, thd->used_tables=0; // Updated by setup_fields if (join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, - select_lex, unit, tables_and_fields_initied)) + select_lex, unit)) { goto err; } @@ -4313,10 +4317,11 @@ COND *eliminate_not_funcs(COND *cond) static COND * optimize_cond(COND *conds,Item::cond_result *cond_value) { + DBUG_ENTER("optimize_cond"); if (!conds) { *cond_value= Item::COND_TRUE; - return conds; + DBUG_RETURN(conds); } DBUG_EXECUTE("where",print_where(conds,"original");); /* eliminate NOT operators */ @@ -4331,7 +4336,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value) DBUG_EXECUTE("where",print_where(conds,"after const change");); conds=remove_eq_conds(conds,cond_value) ; DBUG_EXECUTE("info",print_where(conds,"after remove");); - return conds; + DBUG_RETURN(conds); } @@ -4548,6 +4553,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ****************************************************************************/ /* + Create field for temporary table from given field + + SYNOPSIS + create_tmp_field_from_field() + thd Thread handler + org_field field from which new field will be created + item Item to create a field for + table Temporary table + modify_item 1 if item->result_field should point to new item. + This is relevent for how fill_record() is going to + work: + If modify_item is 1 then fill_record() will update + the record in the original table. + If modify_item is 0 then fill_record() will update + the temporary table + + RETURN + 0 on error + new_created field +*/ +static Field* create_tmp_field_from_field(THD *thd, + Field* org_field, + Item *item, + TABLE *table, + bool modify_item) +{ + Field *new_field; + + // The following should always be true + if ((new_field= org_field->new_field(&thd->mem_root,table))) + { + if (modify_item) + ((Item_field *)item)->result_field= new_field; + else + new_field->field_name= item->name; + if (org_field->maybe_null()) + new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join + if (org_field->type() == FIELD_TYPE_VAR_STRING) + table->db_create_options|= HA_OPTION_PACK_RECORD; + } + return new_field; +} + +/* + Create field for temporary table using type of given item + + SYNOPSIS + create_tmp_field_from_item() + thd Thread handler + item Item to create a field for + table Temporary table + copy_func If set and item is a function, store copy of item + in this array + modify_item 1 if item->result_field should point to new item. + This is relevent for how fill_record() is going to + work: + If modify_item is 1 then fill_record() will update + the record in the original table. + If modify_item is 0 then fill_record() will update + the temporary table + + RETURN + 0 on error + new_created field +*/ +static Field* create_tmp_field_from_item(THD *thd, + Item *item, + TABLE *table, + Item ***copy_func, + bool modify_item) +{ + bool maybe_null=item->maybe_null; + Field *new_field; + LINT_INIT(new_field); + + switch (item->result_type()) { + case REAL_RESULT: + new_field=new Field_double(item->max_length, maybe_null, + item->name, table, item->decimals); + break; + case INT_RESULT: + new_field=new Field_longlong(item->max_length, maybe_null, + item->name, table, item->unsigned_flag); + break; + case STRING_RESULT: + if (item->max_length > 255) + new_field= new Field_blob(item->max_length, maybe_null, + item->name, table, + item->collation.collation); + else + new_field= new Field_string(item->max_length, maybe_null, + item->name, table, + item->collation.collation); + break; + case ROW_RESULT: + default: + // This case should never be choosen + DBUG_ASSERT(0); + new_field= 0; // to satisfy compiler (uninitialized variable) + break; + } + if (copy_func && item->is_result_field()) + *((*copy_func)++) = item; // Save for copy_funcs + if (modify_item) + item->set_result_field(new_field); + return new_field; +} + +/* Create field for temporary table SYNOPSIS @@ -4558,6 +4672,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) type Type of item (normally item->type) copy_func If set and item is a function, store copy of item in this array + from_field if field will be created using other field as example, + pointer example field will be written here group 1 if we are going to do a relative group by on result modify_item 1 if item->result_field should point to new item. This is relevent for how fill_record() is going to @@ -4624,24 +4740,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, return 0; // Error } case Item::FIELD_ITEM: - { - Field *org_field=((Item_field*) item)->field,*new_field; - - *from_field=org_field; - // The following should always be true - if ((new_field= org_field->new_field(&thd->mem_root,table))) - { - if (modify_item) - ((Item_field*) item)->result_field= new_field; - else - new_field->field_name=item->name; - if (org_field->maybe_null()) - new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join - if (org_field->type()==FIELD_TYPE_VAR_STRING) - table->db_create_options|= HA_OPTION_PACK_RECORD; - } - return new_field; - } + return create_tmp_field_from_field(thd, (*from_field= + ((Item_field*) item)->field), + item, table, modify_item); case Item::FUNC_ITEM: case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: @@ -4655,40 +4756,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::REF_ITEM: case Item::NULL_ITEM: case Item::VARBIN_ITEM: + return create_tmp_field_from_item(thd, item, table, + copy_func, modify_item); + case Item::TYPE_HOLDER: { - bool maybe_null=item->maybe_null; - Field *new_field; - LINT_INIT(new_field); - - switch (item->result_type()) { - case REAL_RESULT: - new_field=new Field_double(item->max_length,maybe_null, - item->name,table,item->decimals); - break; - case INT_RESULT: - new_field=new Field_longlong(item->max_length,maybe_null, - item->name,table, item->unsigned_flag); - break; - case STRING_RESULT: - if (item->max_length > 255) - new_field= new Field_blob(item->max_length,maybe_null, - item->name,table,item->collation.collation); - else - new_field= new Field_string(item->max_length,maybe_null, - item->name,table,item->collation.collation); - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - new_field= 0; // to satisfy compiler (uninitialized variable) - break; - } - if (copy_func && item->is_result_field()) - *((*copy_func)++) = item; // Save for copy_funcs - if (modify_item) - item->set_result_field(new_field); - return new_field; + Field *example= ((Item_type_holder *)item)->example(); + if (example) + return create_tmp_field_from_field(thd, example, item, table, 0); + return create_tmp_field_from_item(thd, item, table, copy_func, 0); } default: // Dosen't have to be stored return 0; @@ -7243,7 +7318,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) entry->file->info(HA_STATUS_VARIABLE); if (entry->db_type == DB_TYPE_HEAP || (!entry->blob_fields && - ((ALIGN_SIZE(reclength) +sizeof(HASH_LINK)) * entry->file->records < + ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records < thd->variables.sortbuff_size))) error=remove_dup_with_hash_index(join->thd, entry, field_count, first_field, @@ -7753,8 +7828,6 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, Item *itemptr=*order->item; if (itemptr->type() == Item::INT_ITEM) { /* Order by position */ - Item *item=0; - uint count= (uint) ((Item_int*)itemptr)->value; if (!count || count > fields.elements) { @@ -8327,10 +8400,10 @@ bool JOIN::alloc_func_list() } -bool JOIN::make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields, +bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields, bool before_group_by) { - List_iterator_fast<Item> it(all_fields); + List_iterator_fast<Item> it(field_list); Item_sum **func; Item *item; DBUG_ENTER("make_sum_func_list"); @@ -8349,7 +8422,7 @@ bool JOIN::make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields, if (before_group_by && rollup.state == ROLLUP::STATE_INITED) { rollup.state= ROLLUP::STATE_READY; - if (rollup_make_fields(all_fields, send_fields, &func)) + if (rollup_make_fields(field_list, send_fields, &func)) DBUG_RETURN(TRUE); // Should never happen } else if (rollup.state == ROLLUP::STATE_NONE) @@ -8652,12 +8725,12 @@ bool JOIN::rollup_init() */ for (i= 0 ; i < send_group_parts ; i++) { - List<Item> *fields= &rollup.fields[i]; - fields->empty(); + List<Item> *rollup_fields= &rollup.fields[i]; + rollup_fields->empty(); rollup.ref_pointer_arrays[i]= ref_array; ref_array+= all_fields.elements; for (j=0 ; j < fields_list.elements ; j++) - fields->push_back(rollup.item_null); + rollup_fields->push_back(rollup.item_null); } return 0; } @@ -8668,8 +8741,8 @@ bool JOIN::rollup_init() SYNOPSIS rollup_make_fields() - all_fields List of all fields (hidden and real ones) - fields Pointer to selected fields + fields_arg List of all fields (hidden and real ones) + sel_fields Pointer to selected fields func Store here a pointer to all fields IMPLEMENTATION: @@ -8681,11 +8754,11 @@ bool JOIN::rollup_init() 1 on error */ -bool JOIN::rollup_make_fields(List<Item> &all_fields, List<Item> &fields, +bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, Item_sum ***func) { - List_iterator_fast<Item> it(all_fields); - Item *first_field= fields.head(); + List_iterator_fast<Item> it(fields_arg); + Item *first_field= sel_fields.head(); uint level; /* @@ -8720,7 +8793,7 @@ bool JOIN::rollup_make_fields(List<Item> &all_fields, List<Item> &fields, ORDER *start_group; /* Point to first hidden field */ - Item **ref_array= ref_array_start + all_fields.elements-1; + Item **ref_array= ref_array_start + fields_arg.elements-1; /* Remember where the sum functions ends for the previous level */ sum_funcs_end[pos+1]= *func; @@ -8760,10 +8833,10 @@ bool JOIN::rollup_make_fields(List<Item> &all_fields, List<Item> &fields, else if (real_fields) { /* Check if this is something that is part of this group by */ - ORDER *group; - for (group= start_group ; group ; group= group->next) + ORDER *group_tmp; + for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next) { - if (*group->item == item) + if (*group_tmp->item == item) { /* This is an element that is used by the GROUP BY and should be @@ -8870,7 +8943,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, DBUG_ENTER("select_describe"); DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s", (ulong)join->select_lex, join->select_lex->type, - message)); + message ? message : "NULL")); /* Don't log this into the slow query log */ select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED); join->unit->offset_limit_cnt= 0; @@ -9149,7 +9222,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, select_lex->having, (ORDER*) thd->lex->proc_list.first, select_lex->options | thd->options | SELECT_DESCRIBE, - result, unit, select_lex, 0); + result, unit, select_lex); DBUG_RETURN(res); } @@ -9238,8 +9311,8 @@ void st_select_lex::print(THD *thd, String *str) next_on= 0; } - TABLE_LIST *next; - if ((next= table->next)) + TABLE_LIST *next_table; + if ((next_table= table->next)) { if (table->outer_join & JOIN_TYPE_RIGHT) { @@ -9248,9 +9321,9 @@ void st_select_lex::print(THD *thd, String *str) table->on_expr) next_on= table->on_expr; } - else if (next->straight) + else if (next_table->straight) str->append(" straight_join ", 15); - else if (next->outer_join & JOIN_TYPE_LEFT) + else if (next_table->outer_join & JOIN_TYPE_LEFT) str->append(" left join ", 11); else str->append(" join ", 6); @@ -9258,17 +9331,17 @@ void st_select_lex::print(THD *thd, String *str) } } - //where - Item *where= this->where; + // Where + Item *cur_where= where; if (join) - where= join->conds; - if (where) + cur_where= join->conds; + if (cur_where) { str->append(" where ", 7); - where->print(str); + cur_where->print(str); } - //group by & olap + // group by & olap if (group_list.elements) { str->append(" group by ", 10); @@ -9286,15 +9359,15 @@ void st_select_lex::print(THD *thd, String *str) } } - //having - Item *having= this->having; + // having + Item *cur_having= having; if (join) - having= join->having; + cur_having= join->having; - if (having) + if (cur_having) { str->append(" having ", 8); - having->print(str); + cur_having->print(str); } if (order_list.elements) diff --git a/sql/sql_select.h b/sql/sql_select.h index 53339f7238a..a4672a22384 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -166,11 +166,23 @@ class JOIN :public Sql_alloc JOIN *tmp_join; // copy of this JOIN to be used with temporary tables ROLLUP rollup; // Used with rollup - bool select_distinct, //Is select distinct? - no_order, simple_order, simple_group, - skip_sort_order, need_tmp, - hidden_group_fields, - buffer_result; + bool select_distinct; // Set if SELECT DISTINCT + + /* + simple_xxxxx is set if ORDER/GROUP BY doesn't include any references + to other tables than the first non-constant table in the JOIN. + It's also set if ORDER/GROUP BY is empty. + */ + bool simple_order, simple_group; + /* + Is set only in case if we have a GROUP BY clause + and no ORDER BY after constant elimination of 'order'. + */ + bool no_order; + /* Is set if we have a GROUP BY and we have ORDER BY on a constant. */ + bool skip_sort_order; + + bool need_tmp, hidden_group_fields, buffer_result; DYNAMIC_ARRAY keyuse; Item::cond_result cond_value; List<Item> all_fields; // to store all fields that used in query @@ -195,14 +207,14 @@ class JOIN :public Sql_alloc bool union_part; // this subselect is part of union bool optimized; // flag to avoid double optimization in EXPLAIN - JOIN(THD *thd_arg, List<Item> &fields, ulong select_options_arg, + JOIN(THD *thd_arg, List<Item> &fields_arg, ulong select_options_arg, select_result *result_arg) - :fields_list(fields) + :fields_list(fields_arg) { - init(thd_arg, fields, select_options_arg, result_arg); + init(thd_arg, fields_arg, select_options_arg, result_arg); } - void init(THD *thd_arg, List<Item> &fields, ulong select_options_arg, + void init(THD *thd_arg, List<Item> &fields_arg, ulong select_options_arg, select_result *result_arg) { join_tab= join_tab_save= 0; @@ -235,8 +247,8 @@ class JOIN :public Sql_alloc hidden_group_fields= 0; /*safety*/ buffer_result= test(select_options & OPTION_BUFFER_RESULT) && !test(select_options & OPTION_FOUND_ROWS); - all_fields= fields; - fields_list= fields; + all_fields= fields_arg; + fields_list= fields_arg; error= 0; select= 0; ref_pointer_array= items0= items1= items2= items3= 0; @@ -244,7 +256,7 @@ class JOIN :public Sql_alloc zero_result_cause= 0; optimized= 0; - fields_list= fields; + fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.copy_field=0; tmp_table_param.end_write_records= HA_POS_ERROR; @@ -254,7 +266,7 @@ class JOIN :public Sql_alloc int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); + SELECT_LEX_UNIT *unit); int optimize(); int reinit(); void exec(); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8a11c1de9d4..c176be53c21 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -702,7 +702,6 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, restore_record(table,default_values); // Get empty record Field **ptr,*field; - String *packet= &thd->packet; for (ptr=table->field; (field= *ptr) ; ptr++) { if (!wild || !wild[0] || @@ -892,7 +891,6 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); - String *packet= &thd->packet; KEY *key_info=table->key_info; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < table->keys ; i++,key_info++) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4cc2842e2e7..100f8775445 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1629,7 +1629,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, LEX_STRING *key_cache_name) { HA_CHECK_OPT check_opt; - KEY_CACHE_VAR *key_cache; + KEY_CACHE *key_cache; DBUG_ENTER("mysql_assign_to_keycache"); check_opt.init(); @@ -1644,8 +1644,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, "assign_to_keycache", TL_READ_NO_INSERT, 0, - HA_OPEN_TO_ASSIGN, 0, - &handler::assign_to_keycache)); + 0, 0, &handler::assign_to_keycache)); } @@ -1674,14 +1673,14 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, 0 ok */ -int reassign_keycache_tables(THD *thd, KEY_CACHE_VAR *src_cache, - KEY_CACHE_VAR *dst_cache) +int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, + KEY_CACHE *dst_cache) { DBUG_ENTER("reassign_keycache_tables"); DBUG_ASSERT(src_cache != dst_cache); DBUG_ASSERT(src_cache->in_init); - src_cache->buff_size= 0; // Free key cache + src_cache->param_buff_size= 0; // Free key cache ha_resize_key_cache(src_cache); ha_change_key_cache(src_cache, dst_cache); DBUG_RETURN(0); @@ -1946,7 +1945,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ulonglong next_insert_id; uint save_time_stamp,db_create_options, used_fields; enum db_type old_db_type,new_db_type; - thr_lock_type lock_type; DBUG_ENTER("mysql_alter_table"); thd->proc_info="init"; @@ -2786,7 +2784,6 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) for (table= tables; table; table= table->next) { char table_name[NAME_LEN*2+2]; - bool fatal_error= 0; TABLE *t; strxmov(table_name, table->db ,".", table->real_name, NullS); diff --git a/sql/sql_test.cc b/sql/sql_test.cc index bd527a4154a..cd493fcac30 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -333,9 +333,9 @@ end: } -static int print_key_cache_status(const char *name, KEY_CACHE_VAR *key_cache) +static int print_key_cache_status(const char *name, KEY_CACHE *key_cache) { - if (!key_cache->cache) + if (!key_cache->key_cache_inited) { printf("%s: Not in use\n", name); } @@ -353,11 +353,11 @@ writes: %10lu\n\ r_requests: %10lu\n\ reads: %10lu\n\n", name, - (ulong) key_cache->buff_size, key_cache->block_size, - key_cache->division_limit, key_cache->age_threshold, - key_cache->blocks_used,key_cache->blocks_changed, - key_cache->cache_w_requests,key_cache->cache_write, - key_cache->cache_r_requests,key_cache->cache_read); + (ulong) key_cache->param_buff_size, key_cache->param_block_size, + key_cache->param_division_limit, key_cache->param_age_threshold, + key_cache->global_blocks_used,key_cache->global_blocks_changed, + key_cache->global_cache_w_requests,key_cache->global_cache_write, + key_cache->global_cache_r_requests,key_cache->global_cache_read); } return 0; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8900d48ee4f..33204608fb1 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -25,11 +25,11 @@ #include "sql_select.h" int mysql_union(THD *thd, LEX *lex, select_result *result, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied) + SELECT_LEX_UNIT *unit) { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result, tables_and_fields_initied))) + if (!(res= unit->prepare(thd, result))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -59,12 +59,6 @@ select_union::~select_union() int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u) { unit= u; - if (not_describe && list.elements != table->fields) - { - my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, - ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); - return -1; - } return 0; } @@ -112,12 +106,12 @@ bool select_union::flush() } -int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, - bool tables_and_fields_initied) +int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result) { - SELECT_LEX *lex_select_save= thd->lex->current_select; - SELECT_LEX *select_cursor,*sl; - DBUG_ENTER("st_select_lex_unit::prepare"); + SELECT_LEX *lex_select_save= thd_arg->lex->current_select; + SELECT_LEX *sl, *first_select; + select_result *tmp_result; + DBUG_ENTER("st_select_lex_unit::prepare"); /* result object should be reassigned even if preparing already done for @@ -129,75 +123,32 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, DBUG_RETURN(0); prepared= 1; res= 0; - found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS; - TMP_TABLE_PARAM tmp_table_param; - t_and_f= tables_and_fields_initied; - bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM)); - thd->lex->current_select= sl= select_cursor= first_select_in_union(); + thd_arg->lex->current_select= sl= first_select= first_select_in_union(); + found_rows_for_union= first_select->options & OPTION_FOUND_ROWS; + /* Global option */ - if (t_and_f) + + if (first_select->next_select()) { - // Item list and tables will be initialized by mysql_derived - item_list= select_cursor->item_list; + if (!(tmp_result= union_result= new select_union(0))) + goto err; + union_result->not_describe= 1; + union_result->tmp_table_param.init(); } else { - item_list.empty(); - TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; - - if (setup_tables(first_table) || - setup_wild(thd, first_table, select_cursor->item_list, 0, - select_cursor->with_wild)) - goto err; - List_iterator<Item> it(select_cursor->item_list); - Item *item; - item_list= select_cursor->item_list; - select_cursor->with_wild= 0; - if (select_cursor->setup_ref_array(thd, - select_cursor->order_list.elements + - select_cursor->group_list.elements) || - setup_fields(thd, select_cursor->ref_pointer_array, first_table, - item_list, 0, 0, 1)) - goto err; - // Item list should be fix_fielded yet another time in JOIN::prepare - unfix_item_list(item_list); - - t_and_f= 1; - while((item=it++)) - { - item->maybe_null=1; - if (item->type() == Item::FIELD_ITEM) - ((class Item_field *)item)->field->table->maybe_null=1; - } + tmp_result= sel_result; + // single select should be processed like select in p[arantses + first_select->braces= 1; } - tmp_table_param.field_count=item_list.elements; - if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, - (ORDER*) 0, !union_option, - 1, (select_cursor->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, (char*) ""))) - goto err; - table->file->extra(HA_EXTRA_WRITE_CACHE); - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - bzero((char*) &result_table_list,sizeof(result_table_list)); - result_table_list.db= (char*) ""; - result_table_list.real_name=result_table_list.alias= (char*) "union"; - result_table_list.table=table; - - if (!(union_result=new select_union(table))) - goto err; - - union_result->not_describe=1; - union_result->tmp_table_param=tmp_table_param; - for (;sl; sl= sl->next_select()) { - JOIN *join= new JOIN(thd, sl->item_list, - sl->options | thd->options | SELECT_NO_UNLOCK, - union_result); - thd->lex->current_select= sl; + JOIN *join= new JOIN(thd_arg, sl->item_list, + sl->options | thd_arg->options | SELECT_NO_UNLOCK, + tmp_result); + thd_arg->lex->current_select= sl; offset_limit_cnt= sl->offset_limit; select_limit_cnt= sl->select_limit+sl->offset_limit; if (select_limit_cnt < sl->select_limit) @@ -215,29 +166,80 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, (ORDER*) sl->group_list.first, sl->having, (ORDER*) NULL, - sl, this, t_and_f); - t_and_f= 0; - if (res || thd->is_fatal_error) + sl, this); + if (res || thd_arg->is_fatal_error) goto err; + if (sl == first_select) + { + types.empty(); + List_iterator_fast<Item> it(sl->item_list); + Item *item_tmp; + while ((item_tmp= it++)) + { + types.push_back(new Item_type_holder(thd_arg, item_tmp)); + } + + if (thd_arg->is_fatal_error) + goto err; // out of memory + } + else + { + if (types.elements != sl->item_list.elements) + { + my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, + ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); + goto err; + } + List_iterator_fast<Item> it(sl->item_list); + List_iterator_fast<Item> tp(types); + Item *type, *item_tmp; + while ((type= tp++, item_tmp= it++)) + { + if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp)) + DBUG_RETURN(-1); + } + } } - item_list.empty(); - thd->lex->current_select= lex_select_save; + if (first_select->next_select()) { - List_iterator<Item> it(select_cursor->item_list); - Field **field; + union_result->tmp_table_param.field_count= types.elements; + if (!(table= create_tmp_table(thd_arg, + &union_result->tmp_table_param, types, + (ORDER*) 0, !union_option, 1, + (first_select_in_union()->options | + thd_arg->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, (char*) ""))) + goto err; + table->file->extra(HA_EXTRA_WRITE_CACHE); + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + bzero((char*) &result_table_list, sizeof(result_table_list)); + result_table_list.db= (char*) ""; + result_table_list.real_name= result_table_list.alias= (char*) "union"; + result_table_list.table= table; + union_result->set_table(table); - for (field= table->field; *field; field++) + item_list.empty(); + thd_arg->lex.current_select= lex_select_save; { - (void) it++; - if (item_list.push_back(new Item_field(*field))) - DBUG_RETURN(-1); + Field **field; + for (field= table->field; *field; field++) + { + if (item_list.push_back(new Item_field(*field))) + DBUG_RETURN(-1); + } } } + else + first_select->braces= 0; // remove our changes + + thd_arg->lex.current_select= lex_select_save; + + DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0); - DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0); err: - thd->lex->current_select= lex_select_save; + thd_arg->lex->current_select= lex_select_save; DBUG_RETURN(-1); } @@ -372,7 +374,7 @@ int st_select_lex_unit::exec() if (!thd->is_fatal_error) // Check if EOM { - ulong options= thd->options; + ulong options_tmp= thd->options; thd->lex->current_select= fake_select_lex; offset_limit_cnt= global_parameters->offset_limit; select_limit_cnt= global_parameters->select_limit + @@ -381,9 +383,9 @@ int st_select_lex_unit::exec() if (select_limit_cnt < global_parameters->select_limit) select_limit_cnt= HA_POS_ERROR; // no limit if (select_limit_cnt == HA_POS_ERROR) - options&= ~OPTION_FOUND_ROWS; + options_tmp&= ~OPTION_FOUND_ROWS; else if (found_rows_for_union && !thd->lex->describe) - options|= OPTION_FOUND_ROWS; + options_tmp|= OPTION_FOUND_ROWS; fake_select_lex->ftfunc_list= &empty_list; fake_select_lex->table_list.link_in_list((byte *)&result_table_list, (byte **) @@ -418,8 +420,8 @@ int st_select_lex_unit::exec() global_parameters->order_list.elements, (ORDER*)global_parameters->order_list.first, (ORDER*) NULL, NULL, (ORDER*) NULL, - options | SELECT_NO_UNLOCK, - result, this, fake_select_lex, 0); + options_tmp | SELECT_NO_UNLOCK, + result, this, fake_select_lex); if (!res) thd->limit_found_rows = (ulonglong)table->file->records + add_rows; /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a70e784f42a..058c0b6ce7d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -468,7 +468,7 @@ int mysql_multi_update(THD *thd, conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL, options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, - result, unit, select_lex, 0); + result, unit, select_lex); delete result; DBUG_RETURN(res); } @@ -488,7 +488,8 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, Connect fields with tables and create list of tables that are updated */ -int multi_update::prepare(List<Item> ¬_used_values, SELECT_LEX_UNIT *unit) +int multi_update::prepare(List<Item> ¬_used_values, + SELECT_LEX_UNIT *lex_unit) { TABLE_LIST *table_ref; SQL_LIST update; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1b06b7f34f3..a4972231c29 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -727,7 +727,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); insert_values update delete truncate rename show describe load alter optimize keycache preload flush reset purge begin commit rollback savepoint - slave master_def master_defs master_file_def + slave master_def master_defs master_file_def slave_until_opts repair restore backup analyze check start checksum field_list field_list_item field_spec kill column_def key_def keycache_list assign_to_keycache preload_list preload_keys @@ -5435,7 +5435,7 @@ param_marker: '?' { LEX *lex=Lex; - if (YYTHD->prepare_command) + if (YYTHD->command == COM_PREPARE) { lex->param_list.push_back($$=new Item_param((uint)(lex->tok_start-(uchar *)YYTHD->query))); lex->param_count++; diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 1db2124bcee..d00e57df5a1 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -112,7 +112,7 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match) found_pos= pos; } } - return(found_count == 1 && part_match ? found_count : 0); + return(found_count == 1 && part_match ? found_pos : 0); } diff --git a/sql/time.cc b/sql/time.cc index e696918dee3..fe22b80d59d 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -357,7 +357,6 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) const char *end=str+length; const uchar *format_position; bool found_delimitier= 0, found_space= 0; - DATE_TIME_FORMAT *format; DBUG_ENTER("str_to_TIME"); DBUG_PRINT("ENTER",("str: %.*s",length,str)); |