diff options
Diffstat (limited to 'sql')
76 files changed, 1877 insertions, 796 deletions
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index c26b740d24a..9a253d74546 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright 2004-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc index df419e92d0d..63ecc3006dd 100644 --- a/sql/event_parse_data.cc +++ b/sql/event_parse_data.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/event_parse_data.h b/sql/event_parse_data.h index 87a800c2078..8b42eb23937 100644 --- a/sql/event_parse_data.h +++ b/sql/event_parse_data.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/field.cc b/sql/field.cc index e815320bc9e..973170223e4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3835,7 +3835,7 @@ int Field_longlong::store(double nr) error= 1; } else - res=(longlong) (ulonglong) nr; + res=(longlong) double2ulonglong(nr); } else { diff --git a/sql/field.h b/sql/field.h index 81905cc64ae..5136f760fc1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -209,7 +209,7 @@ public: memcpy(ptr, ptr + l_offset, pack_length()); if (null_ptr) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | - null_ptr[l_offset] & null_bit); + (null_ptr[l_offset] & null_bit)); } virtual bool binary() const { return 1; } virtual bool zero_pack() const { return 1; } diff --git a/sql/filesort.cc b/sql/filesort.cc index d23715a0149..8f18471b378 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -566,10 +566,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, if (quick_select) { if ((error= select->quick->get_next())) - { - error= HA_ERR_END_OF_FILE; break; - } file->position(sort_form->record[0]); DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE);); } diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 7b2395673eb..214ee4c99d2 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -451,7 +451,7 @@ int main(int argc,char **argv) printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n"); printf("\ -/* Copyright (C) 2001-2004 MySQL AB\n\ +/* Copyright 2001-2008 MySQL AB, 2008 Sun Microsystems, Inc.\n\ \n\ This program is free software; you can redistribute it and/or modify\n\ it under the terms of the GNU General Public License as published by\n\ diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index be7ca278302..c804b84ca87 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5256,6 +5256,7 @@ int ha_ndbcluster::create(const char *name, strcmp(m_tabname, NDB_SCHEMA_TABLE) == 0)) { DBUG_PRINT("info", ("Schema distribution table not setup")); + DBUG_ASSERT(ndb_schema_share); DBUG_RETURN(HA_ERR_NO_CONNECTION); } single_user_mode = NdbDictionary::Table::SingleUserModeReadWrite; @@ -6083,6 +6084,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, if (!ndb_schema_share) { DBUG_PRINT("info", ("Schema distribution table not setup")); + DBUG_ASSERT(ndb_schema_share); DBUG_RETURN(HA_ERR_NO_CONNECTION); } /* ndb_share reference temporary */ @@ -6264,6 +6266,7 @@ int ha_ndbcluster::delete_table(const char *name) if (!ndb_schema_share) { DBUG_PRINT("info", ("Schema distribution table not setup")); + DBUG_ASSERT(ndb_schema_share); DBUG_RETURN(HA_ERR_NO_CONNECTION); } #endif @@ -6550,8 +6553,11 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked) DBUG_RETURN(res); } #ifdef HAVE_NDB_BINLOG - if (!ndb_binlog_tables_inited && ndb_binlog_running) + if (!ndb_binlog_tables_inited) + { table->db_stat|= HA_READ_ONLY; + sql_print_information("table '%s' opened read only", name); + } #endif DBUG_RETURN(0); } @@ -6915,8 +6921,8 @@ static void ndbcluster_drop_database(handlerton *hton, char *path) if (!ndb_schema_share) { DBUG_PRINT("info", ("Schema distribution table not setup")); + DBUG_ASSERT(ndb_schema_share); DBUG_VOID_RETURN; - //DBUG_RETURN(HA_ERR_NO_CONNECTION); } #endif ndbcluster_drop_database_impl(path); diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 4fd5ee1b402..baf86d739eb 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -815,9 +815,10 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd) " end_pos BIGINT UNSIGNED NOT NULL, " " PRIMARY KEY USING HASH (server_id) ) ENGINE=NDB CHARACTER SET latin1"); - const int no_print_error[5]= {ER_TABLE_EXISTS_ERROR, + const int no_print_error[6]= {ER_TABLE_EXISTS_ERROR, 701, 702, + 721, // Table already exist 4009, 0}; // do not print error 701 etc run_query(thd, buf, end, no_print_error, TRUE); @@ -876,9 +877,10 @@ static int ndbcluster_create_schema_table(THD *thd) " type INT UNSIGNED NOT NULL," " PRIMARY KEY USING HASH (db,name) ) ENGINE=NDB CHARACTER SET latin1"); - const int no_print_error[5]= {ER_TABLE_EXISTS_ERROR, + const int no_print_error[6]= {ER_TABLE_EXISTS_ERROR, 701, 702, + 721, // Table already exist 4009, 0}; // do not print error 701 etc run_query(thd, buf, end, no_print_error, TRUE); @@ -919,12 +921,9 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) { pthread_mutex_lock(&LOCK_open); ndb_binlog_tables_inited= TRUE; - if (ndb_binlog_running) - { - if (ndb_extra_logging) - sql_print_information("NDB Binlog: ndb tables writable"); - close_cached_tables(NULL, NULL, TRUE, FALSE, FALSE); - } + if (ndb_extra_logging) + sql_print_information("NDB Binlog: ndb tables writable"); + close_cached_tables(NULL, NULL, TRUE, FALSE, FALSE); pthread_mutex_unlock(&LOCK_open); /* Signal injector thread that all is setup */ pthread_cond_signal(&injector_cond); @@ -2069,6 +2068,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ndb_schema_share->use_count)); free_share(&ndb_schema_share); ndb_schema_share= 0; + ndb_binlog_tables_inited= 0; pthread_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ @@ -3269,6 +3269,7 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, share->key, share->use_count)); free_share(&ndb_apply_status_share); ndb_apply_status_share= 0; + ndb_binlog_tables_inited= 0; } DBUG_PRINT("error", ("CLUSTER FAILURE EVENT: " "%s received share: 0x%lx op: 0x%lx share op: 0x%lx " @@ -3288,6 +3289,7 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, share->key, share->use_count)); free_share(&ndb_apply_status_share); ndb_apply_status_share= 0; + ndb_binlog_tables_inited= 0; } /* ToDo: remove printout */ if (ndb_extra_logging) @@ -4311,6 +4313,7 @@ err: ndb_schema_share->use_count)); free_share(&ndb_schema_share); ndb_schema_share= 0; + ndb_binlog_tables_inited= 0; pthread_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ } diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0c96b06381c..0e36a868b3e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2818,6 +2818,36 @@ void ha_partition::unlock_row() DBUG_VOID_RETURN; } +/** + Check if semi consistent read was used + + SYNOPSIS + was_semi_consistent_read() + + RETURN VALUE + TRUE Previous read was a semi consistent read + FALSE Previous read was not a semi consistent read + + DESCRIPTION + See handler.h: + In an UPDATE or DELETE, if the row under the cursor was locked by another + transaction, and the engine used an optimistic read of the last + committed row value under the cursor, then the engine returns 1 from this + function. MySQL must NOT try to update this optimistic value. If the + optimistic value does not match the WHERE condition, MySQL can decide to + skip over this row. Currently only works for InnoDB. This can be used to + avoid unnecessary lock waits. + + If this method returns nonzero, it will also signal the storage + engine that the next read will be a locking re-read of the row. +*/ +bool ha_partition::was_semi_consistent_read() +{ + DBUG_ENTER("ha_partition::was_semi_consistent_read"); + DBUG_ASSERT(m_last_part < m_tot_parts && + bitmap_is_set(&(m_part_info->used_partitions), m_last_part)); + DBUG_RETURN(m_file[m_last_part]->was_semi_consistent_read()); +} /** Use semi consistent read if possible @@ -3431,7 +3461,7 @@ int ha_partition::rnd_next(uchar *buf) while (TRUE) { - int result= file->rnd_next(buf); + result= file->rnd_next(buf); if (!result) { m_last_part= part_id; @@ -4785,7 +4815,7 @@ int ha_partition::info(uint flag) /* Calculates statistical variables records: Estimate of number records in table - We report sum (always at least 2) + We report sum (always at least 2 if not empty) deleted: Estimate of number holes in the table due to deletes We report sum @@ -4824,13 +4854,13 @@ int ha_partition::info(uint flag) stats.check_time= file->stats.check_time; } } while (*(++file_array)); - if (stats.records < 2 && + if (stats.records && stats.records < 2 && !(m_file[0]->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT)) stats.records= 2; if (stats.records > 0) stats.mean_rec_length= (ulong) (stats.data_file_length / stats.records); else - stats.mean_rec_length= 1; //? What should we set here + stats.mean_rec_length= 0; } if (flag & HA_STATUS_CONST) { diff --git a/sql/ha_partition.h b/sql/ha_partition.h index dd06d8d647b..8a81a759e2a 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -112,7 +112,7 @@ private: uint m_reorged_parts; // Number of reorganised parts uint m_tot_parts; // Total number of partitions; uint m_no_locks; // For engines like ha_blackhole, which needs no locks - uint m_last_part; // Last file that we update,write + uint m_last_part; // Last file that we update,write,read int m_lock_type; // Remembers type of last // external_lock part_id_range m_part_spec; // Which parts to scan @@ -326,6 +326,10 @@ public: */ virtual void unlock_row(); /* + Check if semi consistent read + */ + virtual bool was_semi_consistent_read(); + /* Call to hint about semi consistent read */ virtual void try_semi_consistent_read(bool); diff --git a/sql/handler.cc b/sql/handler.cc index 675c21d9522..2145d7c84eb 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2656,8 +2656,12 @@ void handler::print_error(int error, myf errflag) break; case HA_ERR_RECORD_FILE_FULL: case HA_ERR_INDEX_FILE_FULL: + { textno=ER_RECORD_FILE_FULL; + /* Write the error message to error log */ + errflag|= ME_NOREFRESH; break; + } case HA_ERR_LOCK_WAIT_TIMEOUT: textno=ER_LOCK_WAIT_TIMEOUT; break; diff --git a/sql/handler.h b/sql/handler.h index a218de6a1e5..d43fc4725dd 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item.cc b/sql/item.cc index 7b7c44b4719..8356dee0560 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -327,7 +327,7 @@ int Item::save_time_in_field(Field *field) { MYSQL_TIME ltime; if (get_time(<ime)) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field, 0); field->set_notnull(); return field->store_time(<ime, MYSQL_TIMESTAMP_TIME); } @@ -337,7 +337,7 @@ int Item::save_date_in_field(Field *field) { MYSQL_TIME ltime; if (get_date(<ime, TIME_FUZZY_DATE)) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field, 0); field->set_notnull(); return field->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); } @@ -1274,13 +1274,26 @@ Item::Type Item_name_const::type() const valid_args guarantees value_item->basic_const_item(); if type is FUNC_ITEM, then we have a fudged item_func_neg() on our hands and return the underlying type. + For Item_func_set_collation() + e.g. NAME_CONST('name', 'value' COLLATE collation) we return its + 'value' argument type. */ - return valid_args ? - (((value_item->type() == FUNC_ITEM) && - (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ? - ((Item_func *) value_item)->key_item()->type() : - value_item->type()) : - NULL_ITEM; + if (!valid_args) + return NULL_ITEM; + Item::Type value_type= value_item->type(); + if (value_type == FUNC_ITEM) + { + /* + The second argument of NAME_CONST('name', 'value') must be + a simple constant item or a NEG_FUNC/COLLATE_FUNC. + */ + DBUG_ASSERT(((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC || + ((Item_func *) value_item)->functype() == + Item_func::COLLATE_FUNC); + return ((Item_func *) value_item)->key_item()->type(); + } + return value_type; } @@ -2090,6 +2103,12 @@ bool Item_field::val_bool_result() } +bool Item_field::is_null_result() +{ + return (null_value=result_field->is_null()); +} + + bool Item_field::eq(const Item *item, bool binary_cmp) const { Item *real_item= ((Item *) item)->real_item(); @@ -2628,7 +2647,7 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type, if (value.time.year > 9999 || value.time.month > 12 || value.time.day > 31 || - time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 || + (time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23) || value.time.minute > 59 || value.time.second > 59) { char buff[MAX_DATE_STRING_REP_LENGTH]; @@ -4840,8 +4859,8 @@ int Item::save_in_field(Field *field, bool no_conversions) { int error; if (result_type() == STRING_RESULT || - result_type() == REAL_RESULT && - field->result_type() == STRING_RESULT) + (result_type() == REAL_RESULT && + field->result_type() == STRING_RESULT)) { String *result; CHARSET_INFO *cs= collation.collation; @@ -5114,6 +5133,9 @@ int Item_hex_string::save_in_field(Field *field, bool no_conversions) ulonglong nr; uint32 length= str_value.length(); + if (!length) + return 1; + if (length > 8) { nr= field->flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX; @@ -5797,6 +5819,15 @@ double Item_ref::val_result() } +bool Item_ref::is_null_result() +{ + if (result_field) + return (null_value=result_field->is_null()); + + return is_null(); +} + + longlong Item_ref::val_int_result() { if (result_field) @@ -5902,7 +5933,9 @@ String *Item_ref::val_str(String* tmp) bool Item_ref::is_null() { DBUG_ASSERT(fixed); - return (*ref)->is_null(); + bool tmp=(*ref)->is_null_result(); + null_value=(*ref)->null_value; + return tmp; } diff --git a/sql/item.h b/sql/item.h index a3c3cbc78c1..be9daf672f0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -729,6 +729,7 @@ public: virtual my_decimal *val_decimal_result(my_decimal *val) { return val_decimal(val); } virtual bool val_bool_result() { return val_bool(); } + virtual bool is_null_result() { return is_null(); } /* bit map of tables used by item */ virtual table_map used_tables() const { return (table_map) 0L; } @@ -1436,6 +1437,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *protocol, String *str_arg); void reset_field(Field *f); bool fix_fields(THD *, Item **); @@ -2178,6 +2180,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *prot, String *tmp); void make_field(Send_field *field); bool fix_fields(THD *, Item **); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c5de0b3df08..bd90dd81365 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -394,19 +394,16 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, TABLE *table= field->table; ulong orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; - my_bitmap_map *old_write_map; - my_bitmap_map *old_read_map; + my_bitmap_map *old_maps[2]; ulonglong orig_field_val; /* original field value if valid */ - LINT_INIT(old_write_map); - LINT_INIT(old_read_map); + LINT_INIT(old_maps[0]); + LINT_INIT(old_maps[1]); LINT_INIT(orig_field_val); if (table) - { - old_write_map= dbug_tmp_use_all_columns(table, table->write_set); - old_read_map= dbug_tmp_use_all_columns(table, table->read_set); - } + dbug_tmp_use_all_columns(table, old_maps, + table->read_set, table->write_set); /* For comparison purposes allow invalid dates like 2000-01-32 */ thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; @@ -441,10 +438,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, thd->variables.sql_mode= orig_sql_mode; thd->count_cuted_fields= orig_count_cuted_fields; if (table) - { - dbug_tmp_restore_column_map(table->write_set, old_write_map); - dbug_tmp_restore_column_map(table->read_set, old_read_map); - } + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_maps); } return result; } @@ -1629,8 +1623,8 @@ void Item_in_optimizer::cleanup() bool Item_in_optimizer::is_null() { - cache->store(args[0]); - return (null_value= (cache->null_value || args[1]->is_null())); + val_int(); + return null_value; } @@ -2719,6 +2713,16 @@ void Item_func_case::fix_length_and_dec() nagg++; if (!(found_types= collect_cmp_types(agg, nagg))) return; + if (with_sum_func || current_thd->lex->current_select->group_list.elements) + { + /* + See TODO commentary in the setup_copy_fields function: + item in a group may be wrapped with an Item_copy_string item. + That item has a STRING_RESULT result type, so we need + to take this type into account. + */ + found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT)); + } for (i= 0; i <= (uint)DECIMAL_RESULT; i++) { diff --git a/sql/item_func.cc b/sql/item_func.cc index 33b5f21774f..34cb50ee7fa 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3808,6 +3808,13 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, } +void Item_func_set_user_var::cleanup() +{ + Item_func::cleanup(); + entry= NULL; +} + + bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists) { if (entry && thd->thread_id == entry_thread_id) @@ -4307,6 +4314,15 @@ my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) } +bool Item_func_set_user_var::is_null_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return is_null(); +} + + void Item_func_set_user_var::print(String *str, enum_query_type query_type) { str->append(STRING_WITH_LEN("(@")); diff --git a/sql/item_func.h b/sql/item_func.h index 3acda817d26..d23d821baf6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -362,7 +362,10 @@ public: Item_func_unsigned(Item *a) :Item_func_signed(a) {} const char *func_name() const { return "cast_as_unsigned"; } void fix_length_and_dec() - { max_length=args[0]->max_length; unsigned_flag=1; } + { + max_length= min(args[0]->max_length, DECIMAL_MAX_PRECISION + 2); + unsigned_flag=1; + } longlong val_int(); virtual void print(String *str, enum_query_type query_type); }; @@ -1332,6 +1335,7 @@ public: longlong val_int_result(); String *str_result(String *str); my_decimal *val_decimal_result(my_decimal *); + bool is_null_result(); bool update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool send(Protocol *protocol, String *str_arg); @@ -1353,6 +1357,7 @@ public: void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); } bool register_field_in_read_map(uchar *arg); bool set_entry(THD *thd, bool create_if_not_exists); + void cleanup(); }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4e01728f71c..fc9375e68a5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1782,6 +1782,12 @@ Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs) Item_string *conv; uint conv_errors; String tmp, cstr, *ostr= val_str(&tmp); + if (null_value) + { + Item *null_item= new Item_null((char *) fully_qualified_func_name()); + null_item->collation.set (tocs); + return null_item; + } cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); if (conv_errors || !(conv= new Item_static_string_func(fully_qualified_func_name(), @@ -2033,10 +2039,11 @@ Item_func_format::Item_func_format(Item *org, Item *dec) void Item_func_format::fix_length_and_dec() { - collation.set(default_charset()); uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen; - max_length= ((char_length + (char_length-args[0]->decimals)/3) * - collation.collation->mbmaxlen); + uint max_sep_count= char_length/3 + (decimals ? 1 : 0) + /*sign*/1; + collation.set(default_charset()); + max_length= (char_length + max_sep_count + decimals) * + collation.collation->mbmaxlen; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index c2b3b954634..1821136cc9d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -654,8 +654,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) return TRUE; // 'item' can be changed during fix_fields - if (!item->fixed && - item->fix_fields(thd, args) || + if ((!item->fixed && item->fix_fields(thd, args)) || (item= args[0])->check_cols(1)) return TRUE; decimals=item->decimals; @@ -981,8 +980,8 @@ void Item_sum_distinct::fix_length_and_dec() integers each <= 2^32. */ if (table_field_type == MYSQL_TYPE_INT24 || - table_field_type >= MYSQL_TYPE_TINY && - table_field_type <= MYSQL_TYPE_LONG) + (table_field_type >= MYSQL_TYPE_TINY && + table_field_type <= MYSQL_TYPE_LONG)) { val.traits= Hybrid_type_traits_fast_decimal::instance(); break; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 843a48ae118..ab20ed17cd7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1033,12 +1033,25 @@ longlong Item_func_month::val_int() } +void Item_func_monthname::fix_length_and_dec() +{ + THD* thd= current_thd; + CHARSET_INFO *cs= thd->variables.collation_connection; + uint32 repertoire= my_charset_repertoire(cs); + locale= thd->variables.lc_time_names; + collation.set(cs, DERIVATION_COERCIBLE, repertoire); + decimals=0; + max_length= locale->max_month_name_length * collation.collation->mbmaxlen; + maybe_null=1; +} + + String* Item_func_monthname::val_str(String* str) { DBUG_ASSERT(fixed == 1); const char *month_name; - uint month= (uint) val_int(); - THD *thd= current_thd; + uint month= (uint) val_int(); + uint err; if (null_value || !month) { @@ -1046,8 +1059,9 @@ String* Item_func_monthname::val_str(String* str) return (String*) 0; } null_value=0; - month_name= thd->variables.lc_time_names->month_names->type_names[month-1]; - str->set(month_name, strlen(month_name), system_charset_info); + month_name= locale->month_names->type_names[month-1]; + str->copy(month_name, strlen(month_name), &my_charset_utf8_bin, + collation.collation, &err); return str; } @@ -1172,19 +1186,32 @@ longlong Item_func_weekday::val_int() odbc_type) + test(odbc_type); } +void Item_func_dayname::fix_length_and_dec() +{ + THD* thd= current_thd; + CHARSET_INFO *cs= thd->variables.collation_connection; + uint32 repertoire= my_charset_repertoire(cs); + locale= thd->variables.lc_time_names; + collation.set(cs, DERIVATION_COERCIBLE, repertoire); + decimals=0; + max_length= locale->max_day_name_length * collation.collation->mbmaxlen; + maybe_null=1; +} + String* Item_func_dayname::val_str(String* str) { DBUG_ASSERT(fixed == 1); uint weekday=(uint) val_int(); // Always Item_func_daynr() const char *day_name; - THD *thd= current_thd; + uint err; if (null_value) return (String*) 0; - day_name= thd->variables.lc_time_names->day_names->type_names[weekday]; - str->set(day_name, strlen(day_name), system_charset_info); + day_name= locale->day_names->type_names[weekday]; + str->copy(day_name, strlen(day_name), &my_charset_utf8_bin, + collation.collation, &err); return str; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 99240b1c759..9e3c2e8c89f 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -116,18 +116,13 @@ public: class Item_func_monthname :public Item_func_month { + MY_LOCALE *locale; public: Item_func_monthname(Item *a) :Item_func_month(a) {} const char *func_name() const { return "monthname"; } String *val_str(String *str); enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() - { - collation.set(&my_charset_bin); - decimals=0; - max_length=10*my_charset_bin.mbmaxlen; - maybe_null=1; - } + void fix_length_and_dec(); bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -291,18 +286,13 @@ public: class Item_func_dayname :public Item_func_weekday { + MY_LOCALE *locale; public: Item_func_dayname(Item *a) :Item_func_weekday(a,0) {} const char *func_name() const { return "dayname"; } String *val_str(String *str); enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() - { - collation.set(&my_charset_bin); - decimals=0; - max_length=9*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; - } + void fix_length_and_dec(); bool check_partition_func_processor(uchar *int_arg) {return TRUE;} }; @@ -429,6 +419,7 @@ public: { return save_time_in_field(field); } + longlong val_int() { return val_int_from_decimal(); } bool result_as_longlong() { return TRUE; } }; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 68d85418324..5601a2b18c6 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1969,6 +1969,13 @@ my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(MY_XPATH *xpath) if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH)) return 1; + if (xpath->item->type() != Item::XPATH_NODESET) + { + xpath->lasttok= xpath->prevtok; + xpath->error= 1; + return 0; + } + my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH); return my_xpath_parse_RelativeLocationPath(xpath); } @@ -1976,7 +1983,6 @@ static int my_xpath_parse_PathExpr(MY_XPATH *xpath) { return my_xpath_parse_LocationPath(xpath) || my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(xpath); - } diff --git a/sql/lock.cc b/sql/lock.cc index faddb8c586c..f36e8d605d3 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/log.cc b/sql/log.cc index fb8669a5731..74dc75702ae 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -207,6 +207,7 @@ public: truncate(0); before_stmt_pos= MY_OFF_T_UNDEF; trans_log.end_of_file= max_binlog_cache_size; + DBUG_ASSERT(empty()); } Rows_log_event *pending() const @@ -1377,8 +1378,6 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->options, OPTION_BEGIN))); - thd->binlog_flush_pending_rows_event(TRUE); - /* NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of only transactional tables. If the transaction contain changes to @@ -1387,6 +1386,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, */ if (end_ev != NULL) { + thd->binlog_flush_pending_rows_event(TRUE); /* Doing a commit or a rollback including non-transactional tables, i.e., ending a transaction where we might write the transaction @@ -1435,6 +1435,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, mysql_bin_log.update_table_map_version(); } + DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL); DBUG_RETURN(error); } @@ -1449,8 +1450,6 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) return 0; } -#define YESNO(X) ((X) ? "yes" : "no") - /** This function is called once after each statement. @@ -1466,6 +1465,7 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) */ static int binlog_commit(handlerton *hton, THD *thd, bool all) { + int error= 0; DBUG_ENTER("binlog_commit"); binlog_trx_data *const trx_data= (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); @@ -1478,60 +1478,11 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) } /* - Decision table for committing a transaction. The top part, the - *conditions* represent different cases that can occur, and hte - bottom part, the *actions*, represent what should be done in that - particular case. - - Real transaction 'all' was true - - Statement in cache There were at least one statement in the - transaction cache - - In transaction We are inside a transaction - - Stmt modified non-trans The statement being committed modified a - non-transactional table - - All modified non-trans Some statement before this one in the - transaction modified a non-transactional - table - - - ============================= = = = = = = = = = = = = = = = = - Real transaction N N N N N N N N N N N N N N N N - Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y - In transaction N N N N Y Y Y Y N N N N Y Y Y Y - Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y - All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y + We commit the transaction if: - Action: (C)ommit/(A)ccumulate C C - C A C - C - - - - A A - A - ============================= = = = = = = = = = = = = = = = = + - We are not in a transaction and committing a statement, or - - ============================= = = = = = = = = = = = = = = = = - Real transaction Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y - Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y - In transaction N N N N Y Y Y Y N N N N Y Y Y Y - Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y - All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y - - (C)ommit/(A)ccumulate/(-) - - - - C C - C - - - - C C - C - ============================= = = = = = = = = = = = = = = = = - - In other words, we commit the transaction if and only if both of - the following are true: - - We are not in a transaction and committing a statement - - - We are in a transaction and one (or more) of the following are - true: - - - A full transaction is committed - - OR - - - A non-transactional statement is committed and there is - no statement cached + - We are in a transaction and a full transaction is committed Otherwise, we accumulate the statement */ @@ -1544,18 +1495,18 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) YESNO(in_transaction), YESNO(thd->transaction.all.modified_non_trans_table), YESNO(thd->transaction.stmt.modified_non_trans_table))); - if (in_transaction && - (all || - (!trx_data->at_least_one_stmt && - thd->transaction.stmt.modified_non_trans_table)) || - !in_transaction && !all) + if (!in_transaction || all) { Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) - int error= binlog_end_trans(thd, trx_data, &qev, all); - DBUG_RETURN(error); + error= binlog_end_trans(thd, trx_data, &qev, all); + goto end; } - DBUG_RETURN(0); + +end: + if (!all) + trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit + DBUG_RETURN(error); } /** @@ -1615,6 +1566,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) */ error= binlog_end_trans(thd, trx_data, 0, all); } + if (!all) + trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback DBUG_RETURN(error); } @@ -2349,6 +2302,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name, MYSQL_BIN_LOG::MYSQL_BIN_LOG() :bytes_written(0), prepared_xids(0), file_id(1), open_count(1), need_start_event(TRUE), m_table_map_version(0), + is_relay_log(0), description_event_for_exec(0), description_event_for_queue(0) { /* @@ -2359,6 +2313,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG() */ index_file_name[0] = 0; bzero((char*) &index_file, sizeof(index_file)); + bzero((char*) &purge_temp, sizeof(purge_temp)); } /* this is called only once */ @@ -2546,7 +2501,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, */ description_event_for_queue->created= 0; /* Don't set log_pos in event header */ - description_event_for_queue->artificial_event=1; + description_event_for_queue->set_artificial_event(); if (description_event_for_queue->write(&log_file)) goto err; @@ -2953,6 +2908,7 @@ err: int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) { int error; + char *to_purge_if_included= NULL; DBUG_ENTER("purge_first_log"); DBUG_ASSERT(is_open()); @@ -2960,36 +2916,20 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name)); pthread_mutex_lock(&LOCK_index); - pthread_mutex_lock(&rli->log_space_lock); - rli->relay_log.purge_logs(rli->group_relay_log_name, included, - 0, 0, &rli->log_space_total); - // Tell the I/O thread to take the relay_log_space_limit into account - rli->ignore_log_space_limit= 0; - pthread_mutex_unlock(&rli->log_space_lock); + to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0)); /* - Ok to broadcast after the critical region as there is no risk of - the mutex being destroyed by this thread later - this helps save - context switches - */ - pthread_cond_broadcast(&rli->log_space_cond); - - /* Read the next log file name from the index file and pass it back to - the caller - If included is true, we want the first relay log; - otherwise we want the one after event_relay_log_name. + the caller. */ - if ((included && (error=find_log_pos(&rli->linfo, NullS, 0))) || - (!included && - ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) || - (error=find_next_log(&rli->linfo, 0))))) + if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) || + (error=find_next_log(&rli->linfo, 0))) { char buff[22]; sql_print_error("next log error: %d offset: %s log: %s included: %d", error, llstr(rli->linfo.index_file_offset,buff), - rli->group_relay_log_name, + rli->event_relay_log_name, included); goto err; } @@ -3017,7 +2957,42 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) /* Store where we are in the new file for the execution thread */ flush_relay_log_info(rli); + DBUG_EXECUTE_IF("crash_before_purge_logs", abort();); + + pthread_mutex_lock(&rli->log_space_lock); + rli->relay_log.purge_logs(to_purge_if_included, included, + 0, 0, &rli->log_space_total); + // Tell the I/O thread to take the relay_log_space_limit into account + rli->ignore_log_space_limit= 0; + pthread_mutex_unlock(&rli->log_space_lock); + + /* + Ok to broadcast after the critical region as there is no risk of + the mutex being destroyed by this thread later - this helps save + context switches + */ + pthread_cond_broadcast(&rli->log_space_cond); + + /* + * Need to update the log pos because purge logs has been called + * after fetching initially the log pos at the begining of the method. + */ + if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0))) + { + char buff[22]; + sql_print_error("next log error: %d offset: %s log: %s included: %d", + error, + llstr(rli->linfo.index_file_offset,buff), + rli->group_relay_log_name, + included); + goto err; + } + + /* If included was passed, rli->linfo should be the first entry. */ + DBUG_ASSERT(!included || rli->linfo.index_file_start_offset == 0); + err: + my_free(to_purge_if_included, MYF(0)); pthread_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -3068,7 +3043,6 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, ulonglong *decrease_log_space) { int error; - int ret = 0; bool exit_loop= 0; LOG_INFO log_info; THD *thd= current_thd; @@ -3077,8 +3051,36 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, if (need_mutex) pthread_mutex_lock(&LOCK_index); - if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) + if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) + { + sql_print_error("MYSQL_LOG::purge_logs was called with file %s not " + "listed in the index.", to_log); goto err; + } + + /* + For crash recovery reasons the index needs to be updated before + any files are deleted. Move files to be deleted into a temp file + to be processed after the index is updated. + */ + if (!my_b_inited(&purge_temp)) + { + if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX, + DISK_BUFFER_SIZE, MYF(MY_WME)))) + { + sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp"); + goto err; + } + } + else + { + if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1))) + { + sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp " + "for write"); + goto err; + } + } /* File name exists in index file; delete until we find this file @@ -3089,6 +3091,61 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && !log_in_use(log_info.log_file_name)) { + if ((error=my_b_write(&purge_temp, (const uchar*)log_info.log_file_name, + strlen(log_info.log_file_name))) || + (error=my_b_write(&purge_temp, (const uchar*)"\n", 1))) + { + sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp", + log_info.log_file_name); + goto err; + } + + if (find_next_log(&log_info, 0) || exit_loop) + break; + } + + /* We know how many files to delete. Update index file. */ + if ((error=update_log_index(&log_info, need_update_threads))) + { + sql_print_error("MSYQL_LOG::purge_logs failed to update the index file"); + goto err; + } + + DBUG_EXECUTE_IF("crash_after_update_index", abort();); + + /* Switch purge_temp for read. */ + if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0))) + { + sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp " + "for read"); + goto err; + } + + /* Read each entry from purge_temp and delete the file. */ + for (;;) + { + uint length; + + if ((length=my_b_gets(&purge_temp, log_info.log_file_name, + FN_REFLEN)) <= 1) + { + if (purge_temp.error) + { + error= purge_temp.error; + sql_print_error("MSYQL_LOG::purge_logs error %d reading from " + "purge_temp", error); + goto err; + } + + /* Reached EOF */ + break; + } + + /* Get rid of the trailing '\n' */ + log_info.log_file_name[length-1]= 0; + + ha_binlog_index_purge_file(current_thd, log_info.log_file_name); + MY_STAT s; if (!my_stat(log_info.log_file_name, &s, MYF(0))) { @@ -3189,23 +3246,10 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, } } } - - ha_binlog_index_purge_file(current_thd, log_info.log_file_name); - - if (find_next_log(&log_info, 0) || exit_loop) - break; - } - - /* - If we get killed -9 here, the sysadmin would have to edit - the log index file after restart - otherwise, this should be safe - */ - error= update_log_index(&log_info, need_update_threads); - if (error == 0) { - error = ret; } err: + close_cached_file(&purge_temp); if (need_mutex) pthread_mutex_unlock(&LOCK_index); DBUG_RETURN(error); @@ -3216,7 +3260,7 @@ err: index file. @param thd Thread pointer - @param before_date Delete all log files before given date. + @param purge_time Delete all log files before given date. @note If any of the logs before the deleted one is in use, @@ -3233,6 +3277,7 @@ err: int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) { int error; + char to_log[FN_REFLEN]; LOG_INFO log_info; MY_STAT stat_area; THD *thd= current_thd; @@ -3240,12 +3285,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) DBUG_ENTER("purge_logs_before_date"); pthread_mutex_lock(&LOCK_index); + to_log[0]= 0; - /* - Delete until we find curren file - or a file that is used or a file - that is older than purge_time. - */ if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/))) goto err; @@ -3295,55 +3336,18 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) } else { - if (stat_area.st_mtime >= purge_time) + if (stat_area.st_mtime < purge_time) + strmake(to_log, + log_info.log_file_name, + sizeof(log_info.log_file_name)); + else break; - if (my_delete(log_info.log_file_name, MYF(0))) - { - if (my_errno == ENOENT) - { - /* It's not fatal even if we can't delete a log file */ - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - } - sql_print_information("Failed to delete file '%s'", - log_info.log_file_name); - my_errno= 0; - } - else - { - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_BINLOG_PURGE_FATAL_ERR, - "a problem with deleting %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", - log_info.log_file_name); - } - else - { - sql_print_information("Failed to delete log file '%s'", - log_info.log_file_name); - } - error= LOG_INFO_FATAL; - goto err; - } - } - ha_binlog_index_purge_file(current_thd, log_info.log_file_name); } if (find_next_log(&log_info, 0)) break; } - /* - If we get killed -9 here, the sysadmin would have to edit - the log index file after restart - otherwise, this should be safe - */ - error= update_log_index(&log_info, 1); + error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0); err: pthread_mutex_unlock(&LOCK_index); @@ -3469,7 +3473,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) to change base names at some point. */ Rotate_log_event r(new_name+dirname_length(new_name), - 0, LOG_EVENT_OFFSET, 0); + 0, LOG_EVENT_OFFSET, is_relay_log ? Rotate_log_event::RELAY_LOG : 0); r.write(&log_file); bytes_written += r.data_written; } diff --git a/sql/log.h b/sql/log.h index 891134a9762..d54df8add3b 100644 --- a/sql/log.h +++ b/sql/log.h @@ -233,6 +233,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG pthread_cond_t update_cond; ulonglong bytes_written; IO_CACHE index_file; + /* + purge_temp is a temp file used in purge_logs so that the index file + can be updated before deleting files from disk, yielding better crash + recovery. It is created on demand the first time purge_logs is called + and then reused for subsequent calls. It is cleaned up in cleanup(). + */ + IO_CACHE purge_temp; char index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary @@ -274,6 +281,10 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG public: MYSQL_LOG::generate_name; MYSQL_LOG::is_open; + + /* This is relay log */ + bool is_relay_log; + /* These describe the log's format. This is used only for relay logs. _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's diff --git a/sql/log_event.cc b/sql/log_event.cc index 0d03593946d..0e400ac2705 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,6 +53,8 @@ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); + static const char *HA_ERR(int i) { switch (i) { @@ -810,9 +812,8 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) if (is_artificial_event()) { /* - We should not do any cleanup on slave when reading this. We - mark this by setting log_pos to 0. Start_log_event_v3() will - detect this on reading and set artificial_event=1 for the event. + Artificial events are automatically generated and do not exist + in master's binary log, so log_pos should be set to 0. */ log_pos= 0; } @@ -2680,7 +2681,7 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db) { - if (different_db= memcmp(print_event_info->db, db, db_len + 1)) + if ((different_db= memcmp(print_event_info->db, db, db_len + 1))) memcpy(print_event_info->db, db, db_len + 1); if (db[0] && different_db) my_b_printf(file, "use %s%s\n", db, print_event_info->delimiter); @@ -2724,11 +2725,13 @@ void Query_log_event::print_query_header(IO_CACHE* file, bool need_comma= 0; my_b_printf(file, "SET "); print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2, - "@@session.foreign_key_checks", &need_comma); + "@@session.foreign_key_checks", &need_comma); print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2, - "@@session.sql_auto_is_null", &need_comma); + "@@session.sql_auto_is_null", &need_comma); print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2, - "@@session.unique_checks", &need_comma); + "@@session.unique_checks", &need_comma); + print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2, + "@@session.autocommit", &need_comma); my_b_printf(file,"%s\n", print_event_info->delimiter); print_event_info->flags2= flags2; } @@ -2893,7 +2896,37 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); - const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); + if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock) + { + /* + Cleaning-up the last statement context: + the terminal event of the current statement flagged with + STMT_END_F got filtered out in ndb circular replication. + */ + int error; + char llbuff[22]; + if ((error= rows_event_stmt_cleanup(const_cast<Relay_log_info*>(rli), thd))) + { + const_cast<Relay_log_info*>(rli)->report(ERROR_LEVEL, error, + "Error in cleaning up after an event preceeding the commit; " + "the group log file/position: %s %s", + const_cast<Relay_log_info*>(rli)->group_master_log_name, + llstr(const_cast<Relay_log_info*>(rli)->group_master_log_pos, + llbuff)); + } + /* + Executing a part of rli->stmt_done() logics that does not deal + with group position change. The part is redundant now but is + future-change-proof addon, e.g if COMMIT handling will start checking + invariants like IN_STMT flag must be off at committing the transaction. + */ + const_cast<Relay_log_info*>(rli)->inc_event_relay_log_pos(); + const_cast<Relay_log_info*>(rli)->clear_flag(Relay_log_info::IN_STMT); + } + else + { + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); + } /* Note: We do not need to execute reset_one_shot_variables() if this @@ -3196,7 +3229,7 @@ Query_log_event::do_shall_skip(Relay_log_info *rli) #ifndef MYSQL_CLIENT Start_log_event_v3::Start_log_event_v3() :Log_event(), created(0), binlog_version(BINLOG_VERSION), - artificial_event(0), dont_set_created(0) + dont_set_created(0) { memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); } @@ -3244,7 +3277,7 @@ void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) my_b_printf(&cache, "# Warning: this binlog was not closed properly. " "Most probably mysqld crashed writing it.\n"); } - if (!artificial_event && created) + if (!is_artificial_event() && created) { #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND /* @@ -3287,8 +3320,6 @@ Start_log_event_v3::Start_log_event_v3(const char* buf, // prevent overrun if log is corrupted on disk server_version[ST_SERVER_VER_LEN-1]= 0; created= uint4korr(buf+ST_CREATED_OFFSET); - /* We use log_pos to mark if this was an artificial event or not */ - artificial_event= (log_pos == 0); dont_set_created= 1; } @@ -3425,7 +3456,8 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) number_of_event_types= LOG_EVENT_TYPES; /* we'll catch my_malloc() error in is_valid() */ post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8), - MYF(MY_ZEROFILL)); + MYF(0)); + /* This long list of assignments is not beautiful, but I see no way to make it nicer, as the right members are #defines, not array members, so @@ -3433,16 +3465,40 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) */ if (post_header_len) { + // Allows us to sanity-check that all events initialized their + // events (see the end of this 'if' block). + IF_DBUG(memset(post_header_len, 255, + number_of_event_types*sizeof(uint8));); + + /* Note: all event types must explicitly fill in their lengths here. */ post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN; post_header_len[QUERY_EVENT-1]= QUERY_HEADER_LEN; + post_header_len[STOP_EVENT-1]= STOP_HEADER_LEN; post_header_len[ROTATE_EVENT-1]= ROTATE_HEADER_LEN; + post_header_len[INTVAR_EVENT-1]= INTVAR_HEADER_LEN; post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN; + post_header_len[SLAVE_EVENT-1]= SLAVE_HEADER_LEN; post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN; post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN; post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN; post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN; - post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1]; + post_header_len[NEW_LOAD_EVENT-1]= NEW_LOAD_HEADER_LEN; + post_header_len[RAND_EVENT-1]= RAND_HEADER_LEN; + post_header_len[USER_VAR_EVENT-1]= USER_VAR_HEADER_LEN; post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN; + post_header_len[XID_EVENT-1]= XID_HEADER_LEN; + post_header_len[BEGIN_LOAD_QUERY_EVENT-1]= BEGIN_LOAD_QUERY_HEADER_LEN; + post_header_len[EXECUTE_LOAD_QUERY_EVENT-1]= EXECUTE_LOAD_QUERY_HEADER_LEN; + /* + The PRE_GA events are never be written to any binlog, but + their lengths are included in Format_description_log_event. + Hence, we need to be assign some value here, to avoid reading + uninitialized memory when the array is written to disk. + */ + post_header_len[PRE_GA_WRITE_ROWS_EVENT-1] = 0; + post_header_len[PRE_GA_UPDATE_ROWS_EVENT-1] = 0; + post_header_len[PRE_GA_DELETE_ROWS_EVENT-1] = 0; + post_header_len[TABLE_MAP_EVENT-1]= TABLE_MAP_HEADER_LEN; post_header_len[WRITE_ROWS_EVENT-1]= ROWS_HEADER_LEN; post_header_len[UPDATE_ROWS_EVENT-1]= ROWS_HEADER_LEN; @@ -3462,9 +3518,14 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) post_header_len[WRITE_ROWS_EVENT-1]= post_header_len[UPDATE_ROWS_EVENT-1]= post_header_len[DELETE_ROWS_EVENT-1]= 6;); - post_header_len[BEGIN_LOAD_QUERY_EVENT-1]= post_header_len[APPEND_BLOCK_EVENT-1]; - post_header_len[EXECUTE_LOAD_QUERY_EVENT-1]= EXECUTE_LOAD_QUERY_HEADER_LEN; post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN; + + // Sanity-check that all post header lengths are initialized. + IF_DBUG({ + int i; + for (i=0; i<number_of_event_types; i++) + assert(post_header_len[i] != 255); + }); } break; @@ -3700,7 +3761,7 @@ int Format_description_log_event::do_apply_event(Relay_log_info const *rli) original place when it comes to us; we'll know this by checking log_pos ("artificial" events have log_pos == 0). */ - if (!artificial_event && created && thd->transaction.all.ha_list) + if (!is_artificial_event() && created && thd->transaction.all.ha_list) { /* This is not an error (XA is safe), just an information */ rli->report(INFORMATION_LEVEL, 0, @@ -4637,6 +4698,8 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg, #endif if (flags & DUP_NAME) new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME)); + if (flags & RELAY_LOG) + set_relay_log_event(); DBUG_VOID_RETURN; } #endif @@ -4708,8 +4771,6 @@ int Rotate_log_event::do_update_pos(Relay_log_info *rli) DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident)); DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf))); - pthread_mutex_lock(&rli->data_lock); - rli->event_relay_log_pos= my_b_tell(rli->cur_log); /* If we are in a transaction or in a group: the only normal case is when the I/O thread was copying a big transaction, then it was @@ -4727,23 +4788,24 @@ int Rotate_log_event::do_update_pos(Relay_log_info *rli) relay log, which shall not change the group positions. */ if ((server_id != ::server_id || rli->replicate_same_server_id) && + !is_relay_log_event() && !rli->is_in_group()) { + pthread_mutex_lock(&rli->data_lock); DBUG_PRINT("info", ("old group_master_log_name: '%s' " "old group_master_log_pos: %lu", rli->group_master_log_name, (ulong) rli->group_master_log_pos)); memcpy(rli->group_master_log_name, new_log_ident, ident_len+1); rli->notify_group_master_log_name_update(); - rli->group_master_log_pos= pos; - strmake(rli->group_relay_log_name, rli->event_relay_log_name, - sizeof(rli->group_relay_log_name) - 1); - rli->notify_group_relay_log_name_update(); - rli->group_relay_log_pos= rli->event_relay_log_pos; + rli->inc_group_relay_log_pos(pos, TRUE /* skip_lock */); DBUG_PRINT("info", ("new group_master_log_name: '%s' " "new group_master_log_pos: %lu", rli->group_master_log_name, (ulong) rli->group_master_log_pos)); + pthread_mutex_unlock(&rli->data_lock); + flush_relay_log_info(rli); + /* Reset thd->options and sql_mode etc, because this could be the signal of a master's downgrade from 5.0 to 4.0. @@ -4757,9 +4819,9 @@ int Rotate_log_event::do_update_pos(Relay_log_info *rli) thd->variables.auto_increment_increment= thd->variables.auto_increment_offset= 1; } - pthread_mutex_unlock(&rli->data_lock); - pthread_cond_broadcast(&rli->data_cond); - flush_relay_log_info(rli); + else + rli->inc_event_relay_log_pos(); + DBUG_RETURN(0); } @@ -4813,7 +4875,9 @@ Intvar_log_event::Intvar_log_event(const char* buf, const Format_description_log_event* description_event) :Log_event(buf, description_event) { - buf+= description_event->common_header_len; + /* The Post-Header is empty. The Varible Data part begins immediately. */ + buf+= description_event->common_header_len + + description_event->post_header_len[INTVAR_EVENT-1]; type= buf[I_TYPE_OFFSET]; val= uint8korr(buf+I_VAL_OFFSET); } @@ -4957,7 +5021,9 @@ Rand_log_event::Rand_log_event(const char* buf, const Format_description_log_event* description_event) :Log_event(buf, description_event) { - buf+= description_event->common_header_len; + /* The Post-Header is empty. The Variable Data part begins immediately. */ + buf+= description_event->common_header_len + + description_event->post_header_len[RAND_EVENT-1]; seed1= uint8korr(buf+RAND_SEED1_OFFSET); seed2= uint8korr(buf+RAND_SEED2_OFFSET); } @@ -5061,7 +5127,9 @@ Xid_log_event(const char* buf, const Format_description_log_event *description_event) :Log_event(buf, description_event) { - buf+= description_event->common_header_len; + /* The Post-Header is empty. The Variable Data part begins immediately. */ + buf+= description_event->common_header_len + + description_event->post_header_len[XID_EVENT-1]; memcpy((char*) &xid, buf, sizeof(xid)); } @@ -5207,7 +5275,9 @@ User_var_log_event(const char* buf, const Format_description_log_event* description_event) :Log_event(buf, description_event) { - buf+= description_event->common_header_len; + /* The Post-Header is empty. The Variable Data part begins immediately. */ + buf+= description_event->common_header_len + + description_event->post_header_len[USER_VAR_EVENT-1]; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; buf+= UV_NAME_LEN_SIZE + name_len; @@ -5907,8 +5977,15 @@ void Create_file_log_event::pack_info(Protocol *protocol) #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ -/* +/** Create_file_log_event::do_apply_event() + Constructor for Create_file_log_event to intantiate an event + from the relay log on the slave. + + @retval + 0 Success + @retval + 1 Failure */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) @@ -5977,7 +6054,7 @@ err: if (fd >= 0) my_close(fd, MYF(0)); thd_proc_info(thd, 0); - return error == 0; + return error != 0; } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -7358,16 +7435,20 @@ Rows_log_event::do_shall_skip(Relay_log_info *rli) return Log_event::do_shall_skip(rli); } -int -Rows_log_event::do_update_pos(Relay_log_info *rli) -{ - DBUG_ENTER("Rows_log_event::do_update_pos"); - int error= 0; - - DBUG_PRINT("info", ("flags: %s", - get_flags(STMT_END_F) ? "STMT_END_F " : "")); +/** + The function is called at Rows_log_event statement commit time, + normally from Rows_log_event::do_update_pos() and possibly from + Query_log_event::do_apply_event() of the COMMIT. + The function commits the last statement for engines, binlog and + releases resources have been allocated for the statement. + + @retval 0 Ok. + @retval non-zero Error at the commit. + */ - if (get_flags(STMT_END_F)) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) +{ + int error; { /* This is the end of a statement or transaction, so close (and @@ -7409,14 +7490,39 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->reset_current_stmt_binlog_row_based(); - rli->cleanup_context(thd, 0); - if (error == 0) + const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0); + } + return error; +} + +/** + The method either increments the relay log position or + commits the current statement and increments the master group + possition if the event is STMT_END_F flagged and + the statement corresponds to the autocommit query (i.e replicated + without wrapping in BEGIN/COMMIT) + + @retval 0 Success + @retval non-zero Error in the statement commit + */ +int +Rows_log_event::do_update_pos(Relay_log_info *rli) +{ + DBUG_ENTER("Rows_log_event::do_update_pos"); + int error= 0; + + DBUG_PRINT("info", ("flags: %s", + get_flags(STMT_END_F) ? "STMT_END_F " : "")); + + if (get_flags(STMT_END_F)) + { + if ((error= rows_event_stmt_cleanup(rli, thd)) == 0) { /* Indicate that a statement is finished. Step the group log position if we are not in a transaction, otherwise increase the event log position. - */ + */ rli->stmt_done(log_pos, when); /* @@ -7430,11 +7536,13 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->clear_error(); } else + { rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", get_type_str(), m_table->s->db.str, m_table->s->table_name.str); + } } else { @@ -8091,6 +8199,9 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability analyze if explicit data is provided for slave's TIMESTAMP columns). */ m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; + + /* Honor next number column if present */ + m_table->next_number_field= m_table->found_next_number_field; return error; } @@ -8099,6 +8210,7 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability * int error) { int local_error= 0; + m_table->next_number_field=0; if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 || m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER) { @@ -9057,7 +9169,17 @@ Incident_log_event::Incident_log_event(const char *buf, uint event_len, DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d", event_len, common_header_len, post_header_len)); - m_incident= static_cast<Incident>(uint2korr(buf + common_header_len)); + int incident_number= uint2korr(buf + common_header_len); + if (incident_number >= INCIDENT_COUNT || + incident_number <= INCIDENT_NONE) + { + // If the incident is not recognized, this binlog event is + // invalid. If we set incident_number to INCIDENT_NONE, the + // invalidity will be detected by is_valid(). + incident_number= INCIDENT_NONE; + DBUG_VOID_RETURN; + } + m_incident= static_cast<Incident>(incident_number); char const *ptr= buf + common_header_len + post_header_len; char const *const str_end= buf + event_len; uint8 len= 0; // Assignment to keep compiler happy @@ -9085,9 +9207,6 @@ Incident_log_event::description() const DBUG_PRINT("info", ("m_incident: %d", m_incident)); - DBUG_ASSERT(0 <= m_incident); - DBUG_ASSERT((size_t) m_incident <= sizeof(description)/sizeof(*description)); - return description[m_incident]; } diff --git a/sql/log_event.h b/sql/log_event.h index 3c109b798d3..1d11d7e2d5f 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -227,14 +227,22 @@ struct sql_ex_info #define QUERY_HEADER_MINIMAL_LEN (4 + 4 + 1 + 2) // where 5.0 differs: 2 for len of N-bytes vars. #define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 2) +#define STOP_HEADER_LEN 0 #define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4) +#define SLAVE_HEADER_LEN 0 #define START_V3_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4) #define ROTATE_HEADER_LEN 8 // this is FROZEN (the Rotate post-header is frozen) +#define INTVAR_HEADER_LEN 0 #define CREATE_FILE_HEADER_LEN 4 #define APPEND_BLOCK_HEADER_LEN 4 #define EXEC_LOAD_HEADER_LEN 4 #define DELETE_FILE_HEADER_LEN 4 +#define NEW_LOAD_HEADER_LEN LOAD_HEADER_LEN +#define RAND_HEADER_LEN 0 +#define USER_VAR_HEADER_LEN 0 #define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES) +#define XID_HEADER_LEN 0 +#define BEGIN_LOAD_QUERY_HEADER_LEN APPEND_BLOCK_HEADER_LEN #define ROWS_HEADER_LEN 8 #define TABLE_MAP_HEADER_LEN 8 #define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1) @@ -319,18 +327,16 @@ struct sql_ex_info #define Q_CHARSET_DATABASE_CODE 8 #define Q_TABLE_MAP_FOR_UPDATE_CODE 9 -/* Intvar event post-header */ +/* Intvar event data */ #define I_TYPE_OFFSET 0 #define I_VAL_OFFSET 1 -/* Rand event post-header */ - +/* Rand event data */ #define RAND_SEED1_OFFSET 0 #define RAND_SEED2_OFFSET 8 -/* User_var event post-header */ - +/* User_var event data */ #define UV_VAL_LEN_SIZE 4 #define UV_VAL_IS_NULL 1 #define UV_VAL_TYPE_SIZE 1 @@ -338,7 +344,6 @@ struct sql_ex_info #define UV_CHARSET_NUMBER_SIZE 4 /* Load event post-header */ - #define L_THREAD_ID_OFFSET 0 #define L_EXEC_TIME_OFFSET 4 #define L_SKIP_LINES_OFFSET 8 @@ -349,7 +354,6 @@ struct sql_ex_info #define L_DATA_OFFSET LOAD_HEADER_LEN /* Rotate event post-header */ - #define R_POS_OFFSET 0 #define R_IDENT_OFFSET 8 @@ -458,6 +462,25 @@ struct sql_ex_info #define LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F 0x10 /** + @def LOG_EVENT_ARTIFICIAL_F + + Artificial events are created arbitarily and not written to binary + log + + These events should not update the master log position when slave + SQL thread executes them. +*/ +#define LOG_EVENT_ARTIFICIAL_F 0x20 + +/** + @def LOG_EVENT_RELAY_LOG_F + + Events with this flag set are created by slave IO thread and written + to relay log +*/ +#define LOG_EVENT_RELAY_LOG_F 0x40 + +/** @def OPTIONS_WRITTEN_TO_BIN_LOG OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must @@ -980,7 +1003,10 @@ public: #endif virtual Log_event_type get_type_code() = 0; virtual bool is_valid() const = 0; - virtual bool is_artificial_event() { return 0; } + void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; } + void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; } + bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; } + bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; } inline bool get_cache_stmt() const { return cache_stmt; } Log_event(const char* buf, const Format_description_log_event *description_event); @@ -2079,12 +2105,6 @@ public: uint16 binlog_version; char server_version[ST_SERVER_VER_LEN]; /* - artifical_event is 1 in the case where this is a generated event that - should not case any cleanup actions. We handle this in the log by - setting log_event == 0 (for now). - */ - bool artificial_event; - /* We set this to 1 if we don't want to have the created time in the log, which is the case when we rollover to a new log. */ @@ -2112,7 +2132,6 @@ public: { return START_V3_HEADER_LEN; //no variable-sized part } - virtual bool is_artificial_event() { return artificial_event; } protected: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) @@ -2206,10 +2225,11 @@ protected: @section Intvar_log_event_binary_format Binary Format - The Post-Header has two components: + The Post-Header for this event type is empty. The Body has two + components: <table> - <caption>Post-Header for Intvar_log_event</caption> + <caption>Body for Intvar_log_event</caption> <tr> <th>Name</th> @@ -2283,11 +2303,12 @@ private: which are stored internally as two 64-bit numbers. @section Rand_log_event_binary_format Binary Format - This event type has no Post-Header. The Body of this event type has - two components: + + The Post-Header for this event type is empty. The Body has two + components: <table> - <caption>Post-Header for Intvar_log_event</caption> + <caption>Body for Rand_log_event</caption> <tr> <th>Name</th> @@ -2532,7 +2553,8 @@ class Rotate_log_event: public Log_event { public: enum { - DUP_NAME= 2 // if constructor should dup the string argument + DUP_NAME= 2, // if constructor should dup the string argument + RELAY_LOG=4 // rotate event for relay log }; const char* new_log_ident; ulonglong pos; @@ -3870,7 +3892,10 @@ public: virtual Log_event_type get_type_code() { return INCIDENT_EVENT; } - virtual bool is_valid() const { return 1; } + virtual bool is_valid() const + { + return m_incident > INCIDENT_NONE && m_incident < INCIDENT_COUNT; + } virtual int get_data_size() { return INCIDENT_HEADER_LEN + 1 + m_message.length; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6367dfee91e..8671f2189bd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -148,15 +148,20 @@ typedef struct my_locale_st TYPELIB *ab_month_names; TYPELIB *day_names; TYPELIB *ab_day_names; + uint max_month_name_length; + uint max_day_name_length; #ifdef __cplusplus my_locale_st(uint number_par, const char *name_par, const char *descr_par, bool is_ascii_par, TYPELIB *month_names_par, TYPELIB *ab_month_names_par, - TYPELIB *day_names_par, TYPELIB *ab_day_names_par) : + TYPELIB *day_names_par, TYPELIB *ab_day_names_par, + uint max_month_name_length_par, uint max_day_name_length_par) : number(number_par), name(name_par), description(descr_par), is_ascii(is_ascii_par), month_names(month_names_par), ab_month_names(ab_month_names_par), - day_names(day_names_par), ab_day_names(ab_day_names_par) + day_names(day_names_par), ab_day_names(ab_day_names_par), + max_month_name_length(max_month_name_length_par), + max_day_name_length(max_day_name_length_par) {} #endif } MY_LOCALE; @@ -857,6 +862,8 @@ struct Query_cache_query_flags unsigned int client_protocol_41:1; unsigned int result_in_binary_protocol:1; unsigned int more_results_exists:1; + unsigned int in_trans:1; + unsigned int autocommit:1; unsigned int pkt_nr; uint character_set_client_num; uint character_set_results_num; @@ -1948,6 +1955,7 @@ extern my_bool opt_log, opt_slow_log; extern ulong log_output_options; extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; +extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress; extern uint volatile thread_count, thread_running, global_read_lock; @@ -2227,6 +2235,7 @@ uint strconvert(CHARSET_INFO *from_cs, const char *from, CHARSET_INFO *to_cs, char *to, uint to_length, uint *errors); uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); +uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length); #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */ #ifdef MYSQL_SERVER uint build_table_filename(char *buff, size_t bufflen, const char *db, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 32a0518c6fd..553179d68f3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -238,6 +238,12 @@ extern "C" int gethostname(char *name, int namelen); extern "C" sig_handler handle_segfault(int sig); +#if defined(__linux__) +#define ENABLE_TEMP_POOL 1 +#else +#define ENABLE_TEMP_POOL 0 +#endif + /* Constants */ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; @@ -383,7 +389,7 @@ static pthread_cond_t COND_thread_cache, COND_flush_thread_cache; /* Global variables */ -bool opt_update_log, opt_bin_log; +bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log; ulong log_output_options; my_bool opt_log_queries_not_using_indexes= 0; @@ -3462,8 +3468,13 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_var_slow_log_path.value= my_strdup(s, MYF(0)); sys_var_slow_log_path.value_length= strlen(s); +#if (ENABLE_TEMP_POOL) if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) return 1; +#else + use_temp_pool= 0; +#endif + if (my_database_names_init()) return 1; @@ -4195,6 +4206,44 @@ void decrement_handler_count() #ifndef EMBEDDED_LIBRARY +#ifndef DBUG_OFF +/* + Debugging helper function to keep the locale database + (see sql_locale.cc) and max_month_name_length and + max_day_name_length variable values in consistent state. +*/ +static void test_lc_time_sz() +{ + DBUG_ENTER("test_lc_time_sz"); + for (MY_LOCALE **loc= my_locales; *loc; loc++) + { + uint max_month_len= 0; + uint max_day_len = 0; + for (const char **month= (*loc)->month_names->type_names; *month; month++) + { + set_if_bigger(max_month_len, + my_numchars_mb(&my_charset_utf8_general_ci, + *month, *month + strlen(*month))); + } + for (const char **day= (*loc)->day_names->type_names; *day; day++) + { + set_if_bigger(max_day_len, + my_numchars_mb(&my_charset_utf8_general_ci, + *day, *day + strlen(*day))); + } + if ((*loc)->max_month_name_length != max_month_len || + (*loc)->max_day_name_length != max_day_len) + { + DBUG_PRINT("Wrong max day name(or month name) length for locale:", + ("%s", (*loc)->name)); + DBUG_ASSERT(0); + } + } + DBUG_VOID_RETURN; +} +#endif//DBUG_OFF + + #ifdef __WIN__ int win_main(int argc, char **argv) #else @@ -4295,6 +4344,10 @@ int main(int argc, char **argv) openlog(libwrapName, LOG_PID, LOG_AUTH); #endif +#ifndef DBUG_OFF + test_lc_time_sz(); +#endif + /* We have enough space for fiddling with the argv, continue */ @@ -5610,7 +5663,8 @@ enum options_mysqld OPT_OLD_MODE, OPT_SLAVE_EXEC_MODE, OPT_GENERAL_LOG_FILE, - OPT_SLOW_QUERY_LOG_FILE + OPT_SLOW_QUERY_LOG_FILE, + OPT_IGNORE_BUILTIN_INNODB }; @@ -5820,6 +5874,9 @@ Disable with --skip-super-large-pages.", (uchar**) &opt_super_large_pages, (uchar**) &opt_super_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"ignore-builtin-innodb", OPT_IGNORE_BUILTIN_INNODB , + "Disable initialization of builtin InnoDB plugin", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection", (uchar**) &opt_init_connect, (uchar**) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -6379,9 +6436,14 @@ log and this option does nothing anymore.", (uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"temp-pool", OPT_TEMP_POOL, +#if (ENABLE_TEMP_POOL) "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.", +#else + "This option is ignored on this OS.", +#endif (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"timed_mutexes", OPT_TIMED_MUTEXES, "Specify whether to time mutexes (only InnoDB mutexes are currently supported)", (uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, @@ -6635,7 +6697,7 @@ The minimum value for this variable is 4096.", {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", (uchar**) &max_user_connections, (uchar**) &max_user_connections, 0, GET_UINT, - REQUIRED_ARG, 0, 1, UINT_MAX, 0, 1, 0}, + REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", (uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG, @@ -6931,13 +6993,15 @@ The minimum value for this variable is 4096.", {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; -static int show_question(THD *thd, SHOW_VAR *var, char *buff) + +static int show_queries(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_LONGLONG; var->value= (char *)&thd->query_id; return 0; } + static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_MY_BOOL; @@ -7353,7 +7417,8 @@ SHOW_VAR status_vars[]= { {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH}, {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH}, #endif /*HAVE_QUERY_CACHE*/ - {"Questions", (char*) &show_question, SHOW_FUNC}, + {"Queries", (char*) &show_queries, SHOW_FUNC}, + {"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS}, #ifdef HAVE_REPLICATION {"Rpl_status", (char*) &show_rpl_status, SHOW_FUNC}, #endif @@ -7503,6 +7568,7 @@ static int mysql_init_variables(void) log_output_options= find_bit_type(log_output_str, &log_output_typelib); opt_bin_log= 0; opt_disable_networking= opt_skip_show_db=0; + opt_ignore_builtin_innodb= 0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0; opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name ! opt_secure_auth= 0; @@ -7801,6 +7867,9 @@ mysqld_get_one_option(int optid, case (int) OPT_BIG_TABLES: thd_startup_options|=OPTION_BIG_TABLES; break; + case (int) OPT_IGNORE_BUILTIN_INNODB: + opt_ignore_builtin_innodb= 1; + break; case (int) OPT_ISAM_LOG: opt_myisam_log=1; break; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index bafc368e415..9f8f17eb4ba 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1245,6 +1245,9 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT() quick->file= NULL; quick_selects.delete_elements(); delete pk_quick_select; + /* It's ok to call the next two even if they are already deinitialized */ + end_read_record(&read_record); + free_io_cache(head); free_root(&alloc,MYF(0)); DBUG_VOID_RETURN; } @@ -2668,7 +2671,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) PART_PRUNE_PARAM prune_param; MEM_ROOT alloc; RANGE_OPT_PARAM *range_par= &prune_param.range_param; - my_bitmap_map *old_read_set, *old_write_set; + my_bitmap_map *old_sets[2]; prune_param.part_info= part_info; init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); @@ -2682,8 +2685,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) DBUG_RETURN(FALSE); } - old_write_set= dbug_tmp_use_all_columns(table, table->write_set); - old_read_set= dbug_tmp_use_all_columns(table, table->read_set); + dbug_tmp_use_all_columns(table, old_sets, + table->read_set, table->write_set); range_par->thd= thd; range_par->table= table; /* range_par->cond doesn't need initialization */ @@ -2773,8 +2776,7 @@ all_used: retval= FALSE; // some partitions are used mark_all_partitions_as_used(prune_param.part_info); end: - dbug_tmp_restore_column_map(table->write_set, old_write_set); - dbug_tmp_restore_column_map(table->read_set, old_read_set); + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); thd->no_errors=0; thd->mem_root= range_par->old_root; free_root(&alloc,MYF(0)); // Return memory & allocator @@ -11145,9 +11147,9 @@ print_key(KEY_PART *key_part, const uchar *key, uint used_length) String tmp(buff,sizeof(buff),&my_charset_bin); uint store_length; TABLE *table= key_part->field->table; - my_bitmap_map *old_write_set, *old_read_set; - old_write_set= dbug_tmp_use_all_columns(table, table->write_set); - old_read_set= dbug_tmp_use_all_columns(table, table->read_set); + my_bitmap_map *old_sets[2]; + + dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); for (; key < key_end; key+=store_length, key_part++) { @@ -11173,8 +11175,7 @@ print_key(KEY_PART *key_part, const uchar *key, uint used_length) if (key+store_length < key_end) fputc('/',DBUG_FILE); } - dbug_tmp_restore_column_map(table->write_set, old_write_set); - dbug_tmp_restore_column_map(table->read_set, old_read_set); + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); } @@ -11182,18 +11183,16 @@ static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg) { char buf[MAX_KEY/8+1]; TABLE *table; - my_bitmap_map *old_read_map, *old_write_map; + my_bitmap_map *old_sets[2]; DBUG_ENTER("print_quick"); if (!quick) DBUG_VOID_RETURN; DBUG_LOCK_FILE; table= quick->head; - old_read_map= dbug_tmp_use_all_columns(table, table->read_set); - old_write_map= dbug_tmp_use_all_columns(table, table->write_set); + dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); quick->dbug_dump(0, TRUE); - dbug_tmp_restore_column_map(table->read_set, old_read_map); - dbug_tmp_restore_column_map(table->write_set, old_write_map); + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); fprintf(DBUG_FILE,"other_keys: 0x%s:\n", needed_reg->print(buf)); diff --git a/sql/parse_file.cc b/sql/parse_file.cc index d3ece194dcd..07ea434e8e0 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -266,6 +266,11 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, if (end_io_cache(&file)) goto err_w_file; + if (opt_sync_frm) { + if (my_sync(handler, MYF(MY_WME))) + goto err_w_file; + } + if (my_close(handler, MYF(MY_WME))) { DBUG_RETURN(TRUE); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 02f2c9b0ab1..e2027d3571e 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -867,6 +867,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, if (part_type != HASH_PARTITION || !list_of_part_fields) { + DBUG_ASSERT(part_expr); err= part_expr->walk(&Item::check_partition_func_processor, 0, NULL); if (!err && is_sub_partitioned() && !list_of_subpart_fields) diff --git a/sql/partition_info.h b/sql/partition_info.h index 703b92305b1..415f955d5d4 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index d7e783f534f..582348608de 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -644,6 +644,16 @@ err: } #endif + +/** + Execute a SHOW SLAVE HOSTS statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @retval FALSE success + @retval TRUE failure +*/ bool show_slave_hosts(THD* thd) { List<Item> field_list; diff --git a/sql/rpl_constants.h b/sql/rpl_constants.h index 426e80a328d..32fb4b8a7f2 100644 --- a/sql/rpl_constants.h +++ b/sql/rpl_constants.h @@ -6,10 +6,10 @@ */ enum Incident { /** No incident */ - INCIDENT_NONE, + INCIDENT_NONE = 0, /** There are possibly lost events in the replication stream */ - INCIDENT_LOST_EVENTS, + INCIDENT_LOST_EVENTS = 1, /** Shall be last event of the enumeration */ INCIDENT_COUNT diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index b6dfd1a1dc8..3a0f784d195 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -155,6 +155,7 @@ int init_relay_log_info(Relay_log_info* rli, sql_print_error("Failed in open_log() called from init_relay_log_info()"); DBUG_RETURN(1); } + rli->relay_log.is_relay_log= TRUE; } /* if file does not exist */ diff --git a/sql/set_var.cc b/sql/set_var.cc index a371c1113ef..f14068fcfcb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -275,6 +275,11 @@ static sys_var_const sys_ft_query_expansion_limit(&vars, static sys_var_const sys_ft_stopword_file(&vars, "ft_stopword_file", OPT_GLOBAL, SHOW_CHAR_PTR, (uchar*) &ft_stopword_file); + +static sys_var_const sys_ignore_builtin_innodb(&vars, "ignore_builtin_innodb", + OPT_GLOBAL, SHOW_BOOL, + (uchar*) &opt_ignore_builtin_innodb); + sys_var_str sys_init_connect(&vars, "init_connect", 0, sys_update_init_connect, sys_default_init_connect,0); @@ -1527,14 +1532,14 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; /* Don't use bigger value than given with --maximum-variable-name=.. */ - if ((ulong) tmp > max_system_variables.*offset) + if (tmp > max_system_variables.*offset) { throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp); tmp= max_system_variables.*offset; } if (option_limits) - tmp= (ulong) fix_unsigned(thd, tmp, option_limits); + tmp= fix_unsigned(thd, tmp, option_limits); #if SIZEOF_LONG < SIZEOF_LONG_LONG else if (tmp > ULONG_MAX) { @@ -1543,6 +1548,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var) } #endif + DBUG_ASSERT(tmp <= ULONG_MAX); if (var->type == OPT_GLOBAL) global_system_variables.*offset= (ulong) tmp; else @@ -3548,6 +3554,7 @@ int set_var_password::check(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!user->host.str) { + DBUG_ASSERT(thd->security_ctx->priv_host); if (*thd->security_ctx->priv_host != 0) { user->host.str= (char *) thd->security_ctx->priv_host; @@ -3559,6 +3566,12 @@ int set_var_password::check(THD *thd) user->host.length= 1; } } + if (!user->user.str) + { + DBUG_ASSERT(thd->security_ctx->priv_user); + user->user.str= (char *) thd->security_ctx->priv_user; + user->user.length= strlen(thd->security_ctx->priv_user); + } /* Returns 1 as the function sends error to client */ return check_change_password(thd, user->host.str, user->user.str, password, strlen(password)) ? 1 : 0; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index fd75fee9737..befd064e3e3 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -571,30 +571,30 @@ ER_ERROR_ON_READ swe "Fick fel vid läsning av '%-.200s' (Felkod %d)" ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ '%-.200s' (ÐÏÍÉÌËÁ: %d)" ER_ERROR_ON_RENAME - cze "Chyba p-Bøi pøejmenování '%-.150s' na '%-.150s' (chybový kód: %d)" - dan "Fejl ved omdøbning af '%-.150s' til '%-.150s' (Fejlkode: %d)" - nla "Fout bij het hernoemen van '%-.150s' naar '%-.150s' (Errcode: %d)" - eng "Error on rename of '%-.150s' to '%-.150s' (errno: %d)" - jps "'%-.150s' ‚ð '%-.150s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Viga faili '%-.150s' ümbernimetamisel '%-.150s'-ks (veakood: %d)" - fre "Erreur en renommant '%-.150s' en '%-.150s' (Errcode: %d)" - ger "Fehler beim Umbenennen von '%-.150s' in '%-.150s' (Fehler: %d)" - greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.150s' to '%-.150s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a '%-.150s' file atnevezesekor '%-.150s'. (hibakod: %d)" - ita "Errore durante la rinominazione da '%-.150s' a '%-.150s' (errno: %d)" - jpn "'%-.150s' ¤ò '%-.150s' ¤Ë rename ¤Ç¤¤Þ¤»¤ó (errno: %d)" - kor "'%-.150s'¸¦ '%-.150s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved omdøping av '%-.150s' til '%-.150s' (Feilkode: %d)" - norwegian-ny "Feil ved omdøyping av '%-.150s' til '%-.150s' (Feilkode: %d)" - pol "B³?d podczas zmieniania nazwy '%-.150s' na '%-.150s' (Kod b³êdu: %d)" - por "Erro ao renomear '%-.150s' para '%-.150s' (erro no. %d)" - rum "Eroare incercind sa renumesc '%-.150s' in '%-.150s' (errno: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.150s' × '%-.150s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri promeni imena '%-.150s' na '%-.150s' (errno: %d)" - slo "Chyba pri premenovávaní '%-.150s' na '%-.150s' (chybový kód: %d)" - spa "Error en el renombrado de '%-.150s' a '%-.150s' (Error: %d)" - swe "Kan inte byta namn från '%-.150s' till '%-.150s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.150s' Õ '%-.150s' (ÐÏÍÉÌËÁ: %d)" + cze "Chyba p-Bøi pøejmenování '%-.210s' na '%-.210s' (chybový kód: %d)" + dan "Fejl ved omdøbning af '%-.210s' til '%-.210s' (Fejlkode: %d)" + nla "Fout bij het hernoemen van '%-.210s' naar '%-.210s' (Errcode: %d)" + eng "Error on rename of '%-.210s' to '%-.210s' (errno: %d)" + jps "'%-.210s' ‚ð '%-.210s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)", + est "Viga faili '%-.210s' ümbernimetamisel '%-.210s'-ks (veakood: %d)" + fre "Erreur en renommant '%-.210s' en '%-.210s' (Errcode: %d)" + ger "Fehler beim Umbenennen von '%-.210s' in '%-.210s' (Fehler: %d)" + greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.210s' to '%-.210s' (êùäéêüò ëÜèïõò: %d)" + hun "Hiba a '%-.210s' file atnevezesekor '%-.210s'. (hibakod: %d)" + ita "Errore durante la rinominazione da '%-.210s' a '%-.210s' (errno: %d)" + jpn "'%-.210s' ¤ò '%-.210s' ¤Ë rename ¤Ç¤¤Þ¤»¤ó (errno: %d)" + kor "'%-.210s'¸¦ '%-.210s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" + nor "Feil ved omdøping av '%-.210s' til '%-.210s' (Feilkode: %d)" + norwegian-ny "Feil ved omdøyping av '%-.210s' til '%-.210s' (Feilkode: %d)" + pol "B³?d podczas zmieniania nazwy '%-.210s' na '%-.210s' (Kod b³êdu: %d)" + por "Erro ao renomear '%-.210s' para '%-.210s' (erro no. %d)" + rum "Eroare incercind sa renumesc '%-.210s' in '%-.210s' (errno: %d)" + rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.210s' × '%-.210s' (ÏÛÉÂËÁ: %d)" + serbian "Greška pri promeni imena '%-.210s' na '%-.210s' (errno: %d)" + slo "Chyba pri premenovávaní '%-.210s' na '%-.210s' (chybový kód: %d)" + spa "Error en el renombrado de '%-.210s' a '%-.210s' (Error: %d)" + swe "Kan inte byta namn från '%-.210s' till '%-.210s' (Felkod: %d)" + ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.210s' Õ '%-.210s' (ÐÏÍÉÌËÁ: %d)" ER_ERROR_ON_WRITE cze "Chyba p-Bøi zápisu do souboru '%-.200s' (chybový kód: %d)" dan "Fejl ved skriving av filen '%-.200s' (Fejlkode: %d)" diff --git a/sql/slave.cc b/sql/slave.cc index 43b70f29a68..22c61b3ec6c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1357,6 +1357,17 @@ int register_slave_on_master(MYSQL* mysql, Master_info *mi, } +/** + Execute a SHOW SLAVE STATUS statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param mi Pointer to Master_info object for the IO thread. + + @retval FALSE success + @retval TRUE failure +*/ bool show_master_info(THD* thd, Master_info* mi) { // TODO: fix this for multi-master @@ -2062,7 +2073,7 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, fewer times, 0 is returned. - init_master_info or init_relay_log_pos failed. (These are called - if a failure occurs when applying the event.)</li> + if a failure occurs when applying the event.) - An error occurred when updating the binlog position. @@ -2307,8 +2318,14 @@ static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi, } -/* Slave I/O Thread entry point */ +/** + Slave IO thread entry point. + + @param arg Pointer to Master_info struct that holds information for + the IO thread. + @return Always 0. +*/ pthread_handler_t handle_slave_io(void *arg) { THD *thd; // needs to be first for thread_stack @@ -2616,8 +2633,14 @@ err: } -/* Slave SQL Thread entry point */ +/** + Slave SQL thread entry point. + + @param arg Pointer to Relay_log_info object that holds information + for the SQL thread. + @return Always 0. +*/ pthread_handler_t handle_slave_sql(void *arg) { THD *thd; /* needs to be first for thread_stack */ @@ -3710,6 +3733,16 @@ static IO_CACHE *reopen_relay_log(Relay_log_info *rli, const char **errmsg) } +/** + Reads next event from the relay log. Should be called from the + slave IO thread. + + @param rli Relay_log_info structure for the slave IO thread. + + @return The event read, or NULL on error. If an error occurs, the + error is reported through the sql_print_information() or + sql_print_error() functions. +*/ static Log_event* next_event(Relay_log_info* rli) { Log_event* ev; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 95cea22ecd9..34b6c483637 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 MySQL AB +/* Copyright 2002-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/spatial.h b/sql/spatial.h index f806861290e..69a1f24506e 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -116,12 +116,12 @@ struct MBR int touches(const MBR *mbr) { /* The following should be safe, even if we compare doubles */ - return ((((mbr->xmin == xmax) || (mbr->xmax == xmin)) && - ((mbr->ymin >= ymin) && (mbr->ymin <= ymax) || - (mbr->ymax >= ymin) && (mbr->ymax <= ymax))) || + return ((((mbr->xmin == xmax) || (mbr->xmax == xmin)) && + (((mbr->ymin >= ymin) && (mbr->ymin <= ymax)) || + ((mbr->ymax >= ymin) && (mbr->ymax <= ymax)))) || (((mbr->ymin == ymax) || (mbr->ymax == ymin)) && - ((mbr->xmin >= xmin) && (mbr->xmin <= xmax) || - (mbr->xmax >= xmin) && (mbr->xmax <= xmax)))); + (((mbr->xmin >= xmin) && (mbr->xmin <= xmax)) || + ((mbr->xmax >= xmin) && (mbr->xmax <= xmax))))); } int within(const MBR *mbr) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0043ef09229..bd940608a07 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -6304,10 +6304,12 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr) } -void update_schema_privilege(TABLE *table, char *buff, const char* db, - const char* t_name, const char* column, - uint col_length, const char *priv, - uint priv_length, const char* is_grantable) +#ifndef NO_EMBEDDED_ACCESS_CHECKS +static bool update_schema_privilege(THD *thd, TABLE *table, char *buff, + const char* db, const char* t_name, + const char* column, uint col_length, + const char *priv, uint priv_length, + const char* is_grantable) { int i= 2; CHARSET_INFO *cs= system_charset_info; @@ -6320,14 +6322,16 @@ void update_schema_privilege(TABLE *table, char *buff, const char* db, if (column) table->field[i++]->store(column, col_length, cs); table->field[i++]->store(priv, priv_length, cs); - table->field[i]->store(is_grantable, (uint) strlen(is_grantable), cs); - table->file->ha_write_row(table->record[0]); + table->field[i]->store(is_grantable, strlen(is_grantable), cs); + return schema_table_store_record(thd, table); } +#endif int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { #ifndef NO_EMBEDDED_ACCESS_CHECKS + int error= 0; uint counter; ACL_USER *acl_user; ulong want_access; @@ -6361,8 +6365,14 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(buff,"'",user,"'@'",host,"'",NullS); if (!(want_access & ~GRANT_ACL)) - update_schema_privilege(table, buff, 0, 0, 0, 0, - STRING_WITH_LEN("USAGE"), is_grantable); + { + if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0, + STRING_WITH_LEN("USAGE"), is_grantable)) + { + error= 1; + goto err; + } + } else { uint priv_id; @@ -6370,16 +6380,22 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1) { if (test_access & j) - update_schema_privilege(table, buff, 0, 0, 0, 0, - command_array[priv_id], - command_lengths[priv_id], is_grantable); + { + if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0, + command_array[priv_id], + command_lengths[priv_id], is_grantable)) + { + error= 1; + goto err; + } + } } } } - +err: pthread_mutex_unlock(&acl_cache->lock); - DBUG_RETURN(0); + DBUG_RETURN(error); #else return(0); #endif @@ -6389,6 +6405,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { #ifndef NO_EMBEDDED_ACCESS_CHECKS + int error= 0; uint counter; ACL_DB *acl_db; ulong want_access; @@ -6426,24 +6443,36 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) } strxmov(buff,"'",user,"'@'",host,"'",NullS); if (!(want_access & ~GRANT_ACL)) - update_schema_privilege(table, buff, acl_db->db, 0, 0, - 0, STRING_WITH_LEN("USAGE"), is_grantable); + { + if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0, + 0, STRING_WITH_LEN("USAGE"), is_grantable)) + { + error= 1; + goto err; + } + } else { int cnt; ulong j,test_access= want_access & ~GRANT_ACL; for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1) if (test_access & j) - update_schema_privilege(table, buff, acl_db->db, 0, 0, 0, - command_array[cnt], command_lengths[cnt], - is_grantable); + { + if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0, 0, + command_array[cnt], command_lengths[cnt], + is_grantable)) + { + error= 1; + goto err; + } + } } } } - +err: pthread_mutex_unlock(&acl_cache->lock); - DBUG_RETURN(0); + DBUG_RETURN(error); #else return (0); #endif @@ -6453,6 +6482,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { #ifndef NO_EMBEDDED_ACCESS_CHECKS + int error= 0; uint index; char buff[100]; TABLE *table= tables->table; @@ -6492,8 +6522,15 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(buff, "'", user, "'@'", host, "'", NullS); if (!test_access) - update_schema_privilege(table, buff, grant_table->db, grant_table->tname, - 0, 0, STRING_WITH_LEN("USAGE"), is_grantable); + { + if (update_schema_privilege(thd, table, buff, grant_table->db, + grant_table->tname, 0, 0, + STRING_WITH_LEN("USAGE"), is_grantable)) + { + error= 1; + goto err; + } + } else { ulong j; @@ -6501,17 +6538,24 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1) { if (test_access & j) - update_schema_privilege(table, buff, grant_table->db, - grant_table->tname, 0, 0, command_array[cnt], - command_lengths[cnt], is_grantable); + { + if (update_schema_privilege(thd, table, buff, grant_table->db, + grant_table->tname, 0, 0, + command_array[cnt], + command_lengths[cnt], is_grantable)) + { + error= 1; + goto err; + } + } } } - } + } } - +err: rw_unlock(&LOCK_grant); - DBUG_RETURN(0); + DBUG_RETURN(error); #else return (0); #endif @@ -6521,6 +6565,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { #ifndef NO_EMBEDDED_ACCESS_CHECKS + int error= 0; uint index; char buff[100]; TABLE *table= tables->table; @@ -6570,22 +6615,28 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) GRANT_COLUMN *grant_column = (GRANT_COLUMN*) hash_element(&grant_table->hash_columns,col_index); if ((grant_column->rights & j) && (table_access & j)) - update_schema_privilege(table, buff, grant_table->db, - grant_table->tname, - grant_column->column, - grant_column->key_length, - command_array[cnt], - command_lengths[cnt], is_grantable); + { + if (update_schema_privilege(thd, table, buff, grant_table->db, + grant_table->tname, + grant_column->column, + grant_column->key_length, + command_array[cnt], + command_lengths[cnt], is_grantable)) + { + error= 1; + goto err; + } + } } } } } } } - +err: rw_unlock(&LOCK_grant); - DBUG_RETURN(0); + DBUG_RETURN(error); #else return (0); #endif diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6dcd11fac71..d17bf085e3b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1111,6 +1111,27 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd) */ if (table->child_l || table->parent) detach_merge_children(table, TRUE); + /* + Reset temporary table lock type to it's default value (TL_WRITE). + + Statements such as INSERT INTO .. SELECT FROM tmp, CREATE TABLE + .. SELECT FROM tmp and UPDATE may under some circumstances modify + the lock type of the tables participating in the statement. This + isn't a problem for non-temporary tables since their lock type is + reset at every open, but the same does not occur for temporary + tables for historical reasons. + + Furthermore, the lock type of temporary tables is not really that + important because they can only be used by one query at a time and + not even twice in a query -- a temporary table is represented by + only one TABLE object. Nonetheless, it's safer from a maintenance + point of view to reset the lock type of this singleton TABLE object + as to not cause problems when the table is reused. + + Even under LOCK TABLES mode its okay to reset the lock type as + LOCK TABLES is allowed (but ignored) for a temporary table. + */ + table->reginfo.lock_type= TL_WRITE; } } } @@ -4681,7 +4702,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) else if (tables->lock_type == TL_READ_DEFAULT) tables->table->reginfo.lock_type= read_lock_type_for_table(thd, tables->table); - else if (tables->table->s->tmp_table == NO_TMP_TABLE) + else tables->table->reginfo.lock_type= tables->lock_type; } tables->table->grant= tables->grant; @@ -5082,8 +5103,15 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) { if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) { - handler::Table_flags flags_some_set= handler::Table_flags(); - handler::Table_flags flags_all_set= ~handler::Table_flags(); + /* + Compute the starting vectors for the computations by creating a + set with all the capabilities bits set and one with no + capabilities bits set. + */ + handler::Table_flags flags_some_set= 0; + handler::Table_flags flags_all_set= + HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; + my_bool multi_engine= FALSE; void* prev_ht= NULL; for (TABLE_LIST *table= tables; table; table= table->next_global) diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 7ca7bef3a56..96e99b57e3c 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -18,7 +18,7 @@ #include "base64.h" /** - Execute a BINLOG statement + Execute a BINLOG statement. To execute the BINLOG command properly the server needs to know which format the BINLOG command's event is in. Therefore, the first @@ -26,6 +26,9 @@ Format_description_log_event, as outputted by mysqlbinlog. This Format_description_log_event is cached in rli->description_event_for_exec. + + @param thd Pointer to THD object for the client thread executing the + statement. */ void mysql_client_binlog_statement(THD* thd) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 1d907bb1f16..fcea4153eb0 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -782,6 +782,9 @@ void query_cache_end_of_result(THD *thd) if (query_cache.is_disabled() || thd->net.query_cache_query == 0) DBUG_VOID_RETURN; + /* Ensure that only complete results are cached. */ + DBUG_ASSERT(thd->main_da.is_eof()); + if (thd->killed) { query_cache_abort(&thd->net); @@ -1003,6 +1006,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) flags.result_in_binary_protocol= (unsigned int) thd->protocol->type(); flags.more_results_exists= test(thd->server_status & SERVER_MORE_RESULTS_EXISTS); + flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS); + flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT); flags.pkt_nr= net->pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; @@ -1024,7 +1029,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \ -def_week_frmt: %lu", +def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.client_long_flag, (int)flags.client_protocol_41, (int)flags.result_in_binary_protocol, @@ -1039,7 +1044,10 @@ def_week_frmt: %lu", flags.max_sort_length, flags.group_concat_max_len, flags.div_precision_increment, - flags.default_week_format)); + flags.default_week_format, + (int)flags.in_trans, + (int)flags.autocommit)); + /* Make InnoDB to release the adaptive hash index latch before acquiring the query cache mutex. @@ -1278,6 +1286,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) flags.result_in_binary_protocol= (unsigned int)thd->protocol->type(); flags.more_results_exists= test(thd->server_status & SERVER_MORE_RESULTS_EXISTS); + flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS); + flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT); flags.pkt_nr= thd->net.pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; flags.character_set_results_num= @@ -1297,7 +1307,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \ -def_week_frmt: %lu", +def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.client_long_flag, (int)flags.client_protocol_41, (int)flags.result_in_binary_protocol, @@ -1312,7 +1322,9 @@ def_week_frmt: %lu", flags.max_sort_length, flags.group_concat_max_len, flags.div_precision_increment, - flags.default_week_format)); + flags.default_week_format, + (int)flags.in_trans, + (int)flags.autocommit)); memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); query_block = (Query_cache_block *) hash_search(&queries, (uchar*) sql, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 58981e4913f..118dc5af68f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3601,7 +3601,6 @@ show_query_type(THD::enum_binlog_query_type qtype) default: DBUG_ASSERT(0 <= qtype && qtype < THD::QUERY_TYPE_COUNT); } - static char buf[64]; sprintf(buf, "UNKNOWN#%d", qtype); return buf; @@ -3661,16 +3660,14 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, if (lex->is_stmt_unsafe() && variables.binlog_format == BINLOG_FORMAT_STMT) { - DBUG_ASSERT(this->query != NULL); push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_UNSAFE_STATEMENT, ER(ER_BINLOG_UNSAFE_STATEMENT)); if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) { - char warn_buf[MYSQL_ERRMSG_SIZE]; - my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", - ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); - sql_print_warning(warn_buf); + sql_print_warning("%s Statement: %.*s", + ER(ER_BINLOG_UNSAFE_STATEMENT), + MYSQL_ERRMSG_SIZE, query_arg); binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; } } diff --git a/sql/sql_class.h b/sql/sql_class.h index 58f5d0080cb..413e2f5be86 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -456,8 +456,15 @@ typedef struct system_status_var ulong com_stmt_fetch; ulong com_stmt_reset; ulong com_stmt_close; - /* + Number of statements sent from the client + */ + ulong questions; + /* + IMPORTANT! + SEE last_system_status_var DEFINITION BELOW. + Below 'last_system_status_var' are all variables which doesn't make any + sense to add to the /global/ status variable counter. Status variables which it does not make sense to add to global status variable counter */ @@ -470,7 +477,7 @@ typedef struct system_status_var counter */ -#define last_system_status_var com_stmt_close +#define last_system_status_var questions void mark_transaction_to_rollback(THD *thd, bool all); @@ -1003,6 +1010,7 @@ show_system_thread(enum_thread_type thread) { #define RETURN_NAME_AS_STRING(NAME) case (NAME): return #NAME switch (thread) { + static char buf[64]; RETURN_NAME_AS_STRING(NON_SYSTEM_THREAD); RETURN_NAME_AS_STRING(SYSTEM_THREAD_DELAYED_INSERT); RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_IO); @@ -1010,9 +1018,11 @@ show_system_thread(enum_thread_type thread) RETURN_NAME_AS_STRING(SYSTEM_THREAD_NDBCLUSTER_BINLOG); RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_SCHEDULER); RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_WORKER); + default: + sprintf(buf, "<UNKNOWN SYSTEM THREAD: %d>", thread); + return buf; } #undef RETURN_NAME_AS_STRING - return "UNKNOWN"; /* keep gcc happy */ } /** @@ -2111,8 +2121,8 @@ public: Don't reset binlog format for NDB binlog injector thread. */ DBUG_PRINT("debug", - ("temporary_tables: %p, in_sub_stmt: %d, system_thread: %s", - temporary_tables, in_sub_stmt, + ("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s", + YESNO(temporary_tables), YESNO(in_sub_stmt), show_system_thread(system_thread))); if ((temporary_tables == NULL) && (in_sub_stmt == 0) && (system_thread != SYSTEM_THREAD_NDBCLUSTER_BINLOG)) diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 1f6c9fdee53..553342f155b 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -86,6 +86,7 @@ class Materialized_cursor: public Server_side_cursor List<Item> item_list; ulong fetch_limit; ulong fetch_count; + bool is_rnd_inited; public: Materialized_cursor(select_result *result, TABLE *table); @@ -197,7 +198,11 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, such command is SHOW VARIABLES or SHOW STATUS. */ if (rc) + { + if (result_materialize->materialized_cursor) + delete result_materialize->materialized_cursor; goto err_open; + } if (sensitive_cursor->is_open()) { @@ -549,7 +554,8 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg, :Server_side_cursor(&table_arg->mem_root, result_arg), table(table_arg), fetch_limit(0), - fetch_count(0) + fetch_count(0), + is_rnd_inited(0) { fake_unit.init_query(); fake_unit.thd= table->in_use; @@ -606,11 +612,12 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) THD *thd= fake_unit.thd; int rc; Query_arena backup_arena; - thd->set_n_backup_active_arena(this, &backup_arena); /* Create a list of fields and start sequential scan */ - rc= (result->prepare(item_list, &fake_unit) || - table->file->ha_rnd_init(TRUE)); + rc= result->prepare(item_list, &fake_unit); + if (!rc && !(rc= table->file->ha_rnd_init(TRUE))) + is_rnd_inited= 1; + thd->restore_active_arena(this, &backup_arena); if (rc == 0) { @@ -685,7 +692,8 @@ void Materialized_cursor::close() { /* Free item_list items */ free_items(); - (void) table->file->ha_rnd_end(); + if (is_rnd_inited) + (void) table->file->ha_rnd_end(); /* We need to grab table->mem_root to prevent free_tmp_table from freeing: the cursor object was allocated in this memory. diff --git a/sql/sql_db.cc b/sql/sql_db.cc index c538dfb08bc..72ae664bba1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -907,7 +907,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) remove_db_from_cache(db); pthread_mutex_unlock(&LOCK_open); - error= -1; /* We temporarily disable the binary log while dropping the objects diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index f7c44152571..d87eafa3e0c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -51,6 +51,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_delete"); + THD::enum_binlog_query_type query_type= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + THD::STMT_QUERY_TYPE : + THD::ROW_QUERY_TYPE; + if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (!(table= table_list->table)) @@ -135,6 +140,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_PRINT("debug", ("Trying to use delete_all_rows()")); if (!(error=table->file->ha_delete_all_rows())) { + /* + If delete_all_rows() is used, it is not possible to log the + query in row format, so we have to log it in statement format. + */ + query_type= THD::STMT_QUERY_TYPE; error= -1; // ok deleted= maybe_deleted; goto cleanup; @@ -374,6 +384,11 @@ cleanup: { if (mysql_bin_log.is_open()) { + bool const is_trans= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + FALSE : + transactional_table; + if (error < 0) thd->clear_error(); /* @@ -381,10 +396,13 @@ cleanup: storage engine does not inject the rows itself, we replicate statement-based; otherwise, 'ha_delete_row()' was used to delete specific rows which we might log row-based. + + Note that TRUNCATE TABLE is not transactional and should + therefore be treated as a DDL. */ - int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE, + int log_result= thd->binlog_query(query_type, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + is_trans, FALSE, killed_status); if (log_result && transactional_table) { @@ -951,6 +969,26 @@ bool multi_delete::send_eof() ****************************************************************************/ /* + Row-by-row truncation if the engine does not support table recreation. + Probably a InnoDB table. +*/ + +static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list) +{ + bool error, save_binlog_row_based= thd->current_stmt_binlog_row_based; + DBUG_ENTER("mysql_truncate_by_delete"); + table_list->lock_type= TL_WRITE; + mysql_init_select(thd->lex); + thd->clear_current_stmt_binlog_row_based(); + error= mysql_delete(thd, table_list, NULL, NULL, HA_POS_ERROR, LL(0), TRUE); + ha_autocommit_or_rollback(thd, error); + end_trans(thd, error ? ROLLBACK : COMMIT); + thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_RETURN(error); +} + + +/* Optimize delete of all rows by doing a full generate of the table This will work even if the .ISM and .ISD tables are destroyed @@ -990,6 +1028,9 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) share->db.str, share->table_name.str, 1)))) (void) rm_temporary_table(table_type, path); + else + thd->thread_specific_used= TRUE; + free_table_share(share); my_free((char*) table,MYF(0)); /* @@ -1055,24 +1096,6 @@ end: DBUG_RETURN(error); trunc_by_del: - /* Probably InnoDB table */ - ulonglong save_options= thd->options; - table_list->lock_type= TL_WRITE; - thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT); - ha_enable_transaction(thd, FALSE); - mysql_init_select(thd->lex); - bool save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); - error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0, - HA_POS_ERROR, LL(0), TRUE); - ha_enable_transaction(thd, TRUE); - /* - Safety, in case the engine ignored ha_enable_transaction(FALSE) - above. Also clears thd->transaction.*. - */ - error= ha_autocommit_or_rollback(thd, error); - ha_commit(thd); - thd->options= save_options; - thd->current_stmt_binlog_row_based= save_binlog_row_based; + error= mysql_truncate_by_delete(thd, table_list); DBUG_RETURN(error); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 79da1936eb9..bd8f9469571 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -177,7 +177,7 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *format, ...) { va_list args; - char warning[ERRMSGSIZE+20]; + char warning[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("push_warning_printf"); DBUG_PRINT("enter",("warning: %u", code)); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2c811ad03a0..322391b63e8 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1690,6 +1690,7 @@ public: class Delayed_insert :public ilink { uint locks_in_memory; + thr_lock_type delayed_lock; public: THD thd; TABLE *table; @@ -1731,6 +1732,8 @@ public: pthread_cond_init(&cond_client,NULL); VOID(pthread_mutex_lock(&LOCK_thread_count)); delayed_insert_threads++; + delayed_lock= global_system_variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } ~Delayed_insert() @@ -2540,7 +2543,7 @@ bool Delayed_insert::handle_inserts(void) table->use_all_columns(); thd_proc_info(&thd, "upgrading lock"); - if (thr_upgrade_write_delay_lock(*thd.lock->locks)) + if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock)) { /* This can happen if thread is killed either by a shutdown diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 983d53a041d..9619d26893c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2002,7 +2002,7 @@ void st_select_lex::print_limit(THD *thd, item->substype() == Item_subselect::ALL_SUBS)) { DBUG_ASSERT(!item->fixed || - select_limit->val_int() == LL(1) && offset_limit == 0); + (select_limit->val_int() == LL(1) && offset_limit == 0)); return; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 24731b600e9..ed6b9e7d8df 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -190,6 +190,15 @@ typedef struct st_lex_server_options char *server_name, *host, *db, *username, *password, *scheme, *socket, *owner; } LEX_SERVER_OPTIONS; + +/** + Structure to hold parameters for CHANGE MASTER or START/STOP SLAVE + or SHOW NEW MASTER. + + Remark: this should not be confused with Master_info (and perhaps + would better be renamed to st_lex_replication_info). Some fields, + e.g., delay, are saved in Relay_log_info, not in Master_info. +*/ typedef struct st_lex_master_info { char *host, *user, *password, *log_file_name; diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index 4e61c664106..3def9864c29 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -49,7 +49,9 @@ MY_LOCALE my_locale_ar_AE &my_locale_typelib_month_names_ar_AE, &my_locale_typelib_ab_month_names_ar_AE, &my_locale_typelib_day_names_ar_AE, - &my_locale_typelib_ab_day_names_ar_AE + &my_locale_typelib_ab_day_names_ar_AE, + 6, + 8 ); /***** LOCALE END ar_AE *****/ @@ -79,7 +81,9 @@ MY_LOCALE my_locale_ar_BH &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_BH *****/ @@ -109,7 +113,9 @@ MY_LOCALE my_locale_ar_JO &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, - &my_locale_typelib_ab_day_names_ar_JO + &my_locale_typelib_ab_day_names_ar_JO, + 12, + 8 ); /***** LOCALE END ar_JO *****/ @@ -139,7 +145,9 @@ MY_LOCALE my_locale_ar_SA &my_locale_typelib_month_names_ar_SA, &my_locale_typelib_ab_month_names_ar_SA, &my_locale_typelib_day_names_ar_SA, - &my_locale_typelib_ab_day_names_ar_SA + &my_locale_typelib_ab_day_names_ar_SA, + 12, + 8 ); /***** LOCALE END ar_SA *****/ @@ -169,7 +177,9 @@ MY_LOCALE my_locale_ar_SY &my_locale_typelib_month_names_ar_SY, &my_locale_typelib_ab_month_names_ar_SY, &my_locale_typelib_day_names_ar_SY, - &my_locale_typelib_ab_day_names_ar_SY + &my_locale_typelib_ab_day_names_ar_SY, + 12, + 8 ); /***** LOCALE END ar_SY *****/ @@ -199,7 +209,9 @@ MY_LOCALE my_locale_be_BY &my_locale_typelib_month_names_be_BY, &my_locale_typelib_ab_month_names_be_BY, &my_locale_typelib_day_names_be_BY, - &my_locale_typelib_ab_day_names_be_BY + &my_locale_typelib_ab_day_names_be_BY, + 10, + 10 ); /***** LOCALE END be_BY *****/ @@ -229,7 +241,9 @@ MY_LOCALE my_locale_bg_BG &my_locale_typelib_month_names_bg_BG, &my_locale_typelib_ab_month_names_bg_BG, &my_locale_typelib_day_names_bg_BG, - &my_locale_typelib_ab_day_names_bg_BG + &my_locale_typelib_ab_day_names_bg_BG, + 9, + 10 ); /***** LOCALE END bg_BG *****/ @@ -259,7 +273,9 @@ MY_LOCALE my_locale_ca_ES &my_locale_typelib_month_names_ca_ES, &my_locale_typelib_ab_month_names_ca_ES, &my_locale_typelib_day_names_ca_ES, - &my_locale_typelib_ab_day_names_ca_ES + &my_locale_typelib_ab_day_names_ca_ES, + 8, + 9 ); /***** LOCALE END ca_ES *****/ @@ -289,7 +305,9 @@ MY_LOCALE my_locale_cs_CZ &my_locale_typelib_month_names_cs_CZ, &my_locale_typelib_ab_month_names_cs_CZ, &my_locale_typelib_day_names_cs_CZ, - &my_locale_typelib_ab_day_names_cs_CZ + &my_locale_typelib_ab_day_names_cs_CZ, + 8, + 7 ); /***** LOCALE END cs_CZ *****/ @@ -319,7 +337,9 @@ MY_LOCALE my_locale_da_DK &my_locale_typelib_month_names_da_DK, &my_locale_typelib_ab_month_names_da_DK, &my_locale_typelib_day_names_da_DK, - &my_locale_typelib_ab_day_names_da_DK + &my_locale_typelib_ab_day_names_da_DK, + 9, + 7 ); /***** LOCALE END da_DK *****/ @@ -349,7 +369,9 @@ MY_LOCALE my_locale_de_AT &my_locale_typelib_month_names_de_AT, &my_locale_typelib_ab_month_names_de_AT, &my_locale_typelib_day_names_de_AT, - &my_locale_typelib_ab_day_names_de_AT + &my_locale_typelib_ab_day_names_de_AT, + 9, + 10 ); /***** LOCALE END de_AT *****/ @@ -379,7 +401,9 @@ MY_LOCALE my_locale_de_DE &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, - &my_locale_typelib_ab_day_names_de_DE + &my_locale_typelib_ab_day_names_de_DE, + 9, + 10 ); /***** LOCALE END de_DE *****/ @@ -409,7 +433,9 @@ MY_LOCALE my_locale_en_US &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_US *****/ @@ -439,7 +465,9 @@ MY_LOCALE my_locale_es_ES &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_ES *****/ @@ -469,7 +497,9 @@ MY_LOCALE my_locale_et_EE &my_locale_typelib_month_names_et_EE, &my_locale_typelib_ab_month_names_et_EE, &my_locale_typelib_day_names_et_EE, - &my_locale_typelib_ab_day_names_et_EE + &my_locale_typelib_ab_day_names_et_EE, + 9, + 9 ); /***** LOCALE END et_EE *****/ @@ -499,7 +529,9 @@ MY_LOCALE my_locale_eu_ES &my_locale_typelib_month_names_eu_ES, &my_locale_typelib_ab_month_names_eu_ES, &my_locale_typelib_day_names_eu_ES, - &my_locale_typelib_ab_day_names_eu_ES + &my_locale_typelib_ab_day_names_eu_ES, + 9, + 10 ); /***** LOCALE END eu_ES *****/ @@ -529,7 +561,9 @@ MY_LOCALE my_locale_fi_FI &my_locale_typelib_month_names_fi_FI, &my_locale_typelib_ab_month_names_fi_FI, &my_locale_typelib_day_names_fi_FI, - &my_locale_typelib_ab_day_names_fi_FI + &my_locale_typelib_ab_day_names_fi_FI, + 9, + 11 ); /***** LOCALE END fi_FI *****/ @@ -559,7 +593,9 @@ MY_LOCALE my_locale_fo_FO &my_locale_typelib_month_names_fo_FO, &my_locale_typelib_ab_month_names_fo_FO, &my_locale_typelib_day_names_fo_FO, - &my_locale_typelib_ab_day_names_fo_FO + &my_locale_typelib_ab_day_names_fo_FO, + 9, + 12 ); /***** LOCALE END fo_FO *****/ @@ -589,7 +625,9 @@ MY_LOCALE my_locale_fr_FR &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, - &my_locale_typelib_ab_day_names_fr_FR + &my_locale_typelib_ab_day_names_fr_FR, + 9, + 8 ); /***** LOCALE END fr_FR *****/ @@ -619,7 +657,9 @@ MY_LOCALE my_locale_gl_ES &my_locale_typelib_month_names_gl_ES, &my_locale_typelib_ab_month_names_gl_ES, &my_locale_typelib_day_names_gl_ES, - &my_locale_typelib_ab_day_names_gl_ES + &my_locale_typelib_ab_day_names_gl_ES, + 8, + 8 ); /***** LOCALE END gl_ES *****/ @@ -649,7 +689,9 @@ MY_LOCALE my_locale_gu_IN &my_locale_typelib_month_names_gu_IN, &my_locale_typelib_ab_month_names_gu_IN, &my_locale_typelib_day_names_gu_IN, - &my_locale_typelib_ab_day_names_gu_IN + &my_locale_typelib_ab_day_names_gu_IN, + 10, + 8 ); /***** LOCALE END gu_IN *****/ @@ -679,7 +721,9 @@ MY_LOCALE my_locale_he_IL &my_locale_typelib_month_names_he_IL, &my_locale_typelib_ab_month_names_he_IL, &my_locale_typelib_day_names_he_IL, - &my_locale_typelib_ab_day_names_he_IL + &my_locale_typelib_ab_day_names_he_IL, + 7, + 5 ); /***** LOCALE END he_IL *****/ @@ -709,7 +753,9 @@ MY_LOCALE my_locale_hi_IN &my_locale_typelib_month_names_hi_IN, &my_locale_typelib_ab_month_names_hi_IN, &my_locale_typelib_day_names_hi_IN, - &my_locale_typelib_ab_day_names_hi_IN + &my_locale_typelib_ab_day_names_hi_IN, + 7, + 9 ); /***** LOCALE END hi_IN *****/ @@ -739,7 +785,9 @@ MY_LOCALE my_locale_hr_HR &my_locale_typelib_month_names_hr_HR, &my_locale_typelib_ab_month_names_hr_HR, &my_locale_typelib_day_names_hr_HR, - &my_locale_typelib_ab_day_names_hr_HR + &my_locale_typelib_ab_day_names_hr_HR, + 8, + 11 ); /***** LOCALE END hr_HR *****/ @@ -769,7 +817,9 @@ MY_LOCALE my_locale_hu_HU &my_locale_typelib_month_names_hu_HU, &my_locale_typelib_ab_month_names_hu_HU, &my_locale_typelib_day_names_hu_HU, - &my_locale_typelib_ab_day_names_hu_HU + &my_locale_typelib_ab_day_names_hu_HU, + 10, + 9 ); /***** LOCALE END hu_HU *****/ @@ -799,7 +849,9 @@ MY_LOCALE my_locale_id_ID &my_locale_typelib_month_names_id_ID, &my_locale_typelib_ab_month_names_id_ID, &my_locale_typelib_day_names_id_ID, - &my_locale_typelib_ab_day_names_id_ID + &my_locale_typelib_ab_day_names_id_ID, + 9, + 6 ); /***** LOCALE END id_ID *****/ @@ -829,7 +881,9 @@ MY_LOCALE my_locale_is_IS &my_locale_typelib_month_names_is_IS, &my_locale_typelib_ab_month_names_is_IS, &my_locale_typelib_day_names_is_IS, - &my_locale_typelib_ab_day_names_is_IS + &my_locale_typelib_ab_day_names_is_IS, + 9, + 12 ); /***** LOCALE END is_IS *****/ @@ -859,7 +913,9 @@ MY_LOCALE my_locale_it_CH &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, - &my_locale_typelib_ab_day_names_it_CH + &my_locale_typelib_ab_day_names_it_CH, + 9, + 9 ); /***** LOCALE END it_CH *****/ @@ -889,7 +945,9 @@ MY_LOCALE my_locale_ja_JP &my_locale_typelib_month_names_ja_JP, &my_locale_typelib_ab_month_names_ja_JP, &my_locale_typelib_day_names_ja_JP, - &my_locale_typelib_ab_day_names_ja_JP + &my_locale_typelib_ab_day_names_ja_JP, + 3, + 3 ); /***** LOCALE END ja_JP *****/ @@ -919,7 +977,9 @@ MY_LOCALE my_locale_ko_KR &my_locale_typelib_month_names_ko_KR, &my_locale_typelib_ab_month_names_ko_KR, &my_locale_typelib_day_names_ko_KR, - &my_locale_typelib_ab_day_names_ko_KR + &my_locale_typelib_ab_day_names_ko_KR, + 3, + 3 ); /***** LOCALE END ko_KR *****/ @@ -949,7 +1009,9 @@ MY_LOCALE my_locale_lt_LT &my_locale_typelib_month_names_lt_LT, &my_locale_typelib_ab_month_names_lt_LT, &my_locale_typelib_day_names_lt_LT, - &my_locale_typelib_ab_day_names_lt_LT + &my_locale_typelib_ab_day_names_lt_LT, + 9, + 14 ); /***** LOCALE END lt_LT *****/ @@ -979,7 +1041,9 @@ MY_LOCALE my_locale_lv_LV &my_locale_typelib_month_names_lv_LV, &my_locale_typelib_ab_month_names_lv_LV, &my_locale_typelib_day_names_lv_LV, - &my_locale_typelib_ab_day_names_lv_LV + &my_locale_typelib_ab_day_names_lv_LV, + 10, + 11 ); /***** LOCALE END lv_LV *****/ @@ -1009,7 +1073,9 @@ MY_LOCALE my_locale_mk_MK &my_locale_typelib_month_names_mk_MK, &my_locale_typelib_ab_month_names_mk_MK, &my_locale_typelib_day_names_mk_MK, - &my_locale_typelib_ab_day_names_mk_MK + &my_locale_typelib_ab_day_names_mk_MK, + 9, + 10 ); /***** LOCALE END mk_MK *****/ @@ -1039,7 +1105,9 @@ MY_LOCALE my_locale_mn_MN &my_locale_typelib_month_names_mn_MN, &my_locale_typelib_ab_month_names_mn_MN, &my_locale_typelib_day_names_mn_MN, - &my_locale_typelib_ab_day_names_mn_MN + &my_locale_typelib_ab_day_names_mn_MN, + 18, + 6 ); /***** LOCALE END mn_MN *****/ @@ -1069,7 +1137,9 @@ MY_LOCALE my_locale_ms_MY &my_locale_typelib_month_names_ms_MY, &my_locale_typelib_ab_month_names_ms_MY, &my_locale_typelib_day_names_ms_MY, - &my_locale_typelib_ab_day_names_ms_MY + &my_locale_typelib_ab_day_names_ms_MY, + 9, + 6 ); /***** LOCALE END ms_MY *****/ @@ -1099,7 +1169,9 @@ MY_LOCALE my_locale_nb_NO &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, - &my_locale_typelib_ab_day_names_nb_NO + &my_locale_typelib_ab_day_names_nb_NO, + 9, + 7 ); /***** LOCALE END nb_NO *****/ @@ -1129,7 +1201,9 @@ MY_LOCALE my_locale_nl_NL &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, - &my_locale_typelib_ab_day_names_nl_NL + &my_locale_typelib_ab_day_names_nl_NL, + 9, + 9 ); /***** LOCALE END nl_NL *****/ @@ -1159,7 +1233,9 @@ MY_LOCALE my_locale_pl_PL &my_locale_typelib_month_names_pl_PL, &my_locale_typelib_ab_month_names_pl_PL, &my_locale_typelib_day_names_pl_PL, - &my_locale_typelib_ab_day_names_pl_PL + &my_locale_typelib_ab_day_names_pl_PL, + 11, + 12 ); /***** LOCALE END pl_PL *****/ @@ -1189,7 +1265,9 @@ MY_LOCALE my_locale_pt_BR &my_locale_typelib_month_names_pt_BR, &my_locale_typelib_ab_month_names_pt_BR, &my_locale_typelib_day_names_pt_BR, - &my_locale_typelib_ab_day_names_pt_BR + &my_locale_typelib_ab_day_names_pt_BR, + 9, + 7 ); /***** LOCALE END pt_BR *****/ @@ -1219,7 +1297,9 @@ MY_LOCALE my_locale_pt_PT &my_locale_typelib_month_names_pt_PT, &my_locale_typelib_ab_month_names_pt_PT, &my_locale_typelib_day_names_pt_PT, - &my_locale_typelib_ab_day_names_pt_PT + &my_locale_typelib_ab_day_names_pt_PT, + 9, + 7 ); /***** LOCALE END pt_PT *****/ @@ -1249,7 +1329,9 @@ MY_LOCALE my_locale_ro_RO &my_locale_typelib_month_names_ro_RO, &my_locale_typelib_ab_month_names_ro_RO, &my_locale_typelib_day_names_ro_RO, - &my_locale_typelib_ab_day_names_ro_RO + &my_locale_typelib_ab_day_names_ro_RO, + 10, + 8 ); /***** LOCALE END ro_RO *****/ @@ -1279,7 +1361,9 @@ MY_LOCALE my_locale_ru_RU &my_locale_typelib_month_names_ru_RU, &my_locale_typelib_ab_month_names_ru_RU, &my_locale_typelib_day_names_ru_RU, - &my_locale_typelib_ab_day_names_ru_RU + &my_locale_typelib_ab_day_names_ru_RU, + 8, + 11 ); /***** LOCALE END ru_RU *****/ @@ -1309,7 +1393,9 @@ MY_LOCALE my_locale_ru_UA &my_locale_typelib_month_names_ru_UA, &my_locale_typelib_ab_month_names_ru_UA, &my_locale_typelib_day_names_ru_UA, - &my_locale_typelib_ab_day_names_ru_UA + &my_locale_typelib_ab_day_names_ru_UA, + 8, + 11 ); /***** LOCALE END ru_UA *****/ @@ -1339,7 +1425,9 @@ MY_LOCALE my_locale_sk_SK &my_locale_typelib_month_names_sk_SK, &my_locale_typelib_ab_month_names_sk_SK, &my_locale_typelib_day_names_sk_SK, - &my_locale_typelib_ab_day_names_sk_SK + &my_locale_typelib_ab_day_names_sk_SK, + 9, + 8 ); /***** LOCALE END sk_SK *****/ @@ -1369,7 +1457,9 @@ MY_LOCALE my_locale_sl_SI &my_locale_typelib_month_names_sl_SI, &my_locale_typelib_ab_month_names_sl_SI, &my_locale_typelib_day_names_sl_SI, - &my_locale_typelib_ab_day_names_sl_SI + &my_locale_typelib_ab_day_names_sl_SI, + 9, + 10 ); /***** LOCALE END sl_SI *****/ @@ -1399,7 +1489,9 @@ MY_LOCALE my_locale_sq_AL &my_locale_typelib_month_names_sq_AL, &my_locale_typelib_ab_month_names_sq_AL, &my_locale_typelib_day_names_sq_AL, - &my_locale_typelib_ab_day_names_sq_AL + &my_locale_typelib_ab_day_names_sq_AL, + 7, + 10 ); /***** LOCALE END sq_AL *****/ @@ -1429,7 +1521,9 @@ MY_LOCALE my_locale_sr_YU &my_locale_typelib_month_names_sr_YU, &my_locale_typelib_ab_month_names_sr_YU, &my_locale_typelib_day_names_sr_YU, - &my_locale_typelib_ab_day_names_sr_YU + &my_locale_typelib_ab_day_names_sr_YU, + 9, + 10 ); /***** LOCALE END sr_YU *****/ @@ -1459,7 +1553,9 @@ MY_LOCALE my_locale_sv_SE &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, - &my_locale_typelib_ab_day_names_sv_SE + &my_locale_typelib_ab_day_names_sv_SE, + 9, + 7 ); /***** LOCALE END sv_SE *****/ @@ -1489,7 +1585,9 @@ MY_LOCALE my_locale_ta_IN &my_locale_typelib_month_names_ta_IN, &my_locale_typelib_ab_month_names_ta_IN, &my_locale_typelib_day_names_ta_IN, - &my_locale_typelib_ab_day_names_ta_IN + &my_locale_typelib_ab_day_names_ta_IN, + 10, + 8 ); /***** LOCALE END ta_IN *****/ @@ -1519,7 +1617,9 @@ MY_LOCALE my_locale_te_IN &my_locale_typelib_month_names_te_IN, &my_locale_typelib_ab_month_names_te_IN, &my_locale_typelib_day_names_te_IN, - &my_locale_typelib_ab_day_names_te_IN + &my_locale_typelib_ab_day_names_te_IN, + 10, + 9 ); /***** LOCALE END te_IN *****/ @@ -1549,7 +1649,9 @@ MY_LOCALE my_locale_th_TH &my_locale_typelib_month_names_th_TH, &my_locale_typelib_ab_month_names_th_TH, &my_locale_typelib_day_names_th_TH, - &my_locale_typelib_ab_day_names_th_TH + &my_locale_typelib_ab_day_names_th_TH, + 10, + 8 ); /***** LOCALE END th_TH *****/ @@ -1579,7 +1681,9 @@ MY_LOCALE my_locale_tr_TR &my_locale_typelib_month_names_tr_TR, &my_locale_typelib_ab_month_names_tr_TR, &my_locale_typelib_day_names_tr_TR, - &my_locale_typelib_ab_day_names_tr_TR + &my_locale_typelib_ab_day_names_tr_TR, + 7, + 9 ); /***** LOCALE END tr_TR *****/ @@ -1609,7 +1713,9 @@ MY_LOCALE my_locale_uk_UA &my_locale_typelib_month_names_uk_UA, &my_locale_typelib_ab_month_names_uk_UA, &my_locale_typelib_day_names_uk_UA, - &my_locale_typelib_ab_day_names_uk_UA + &my_locale_typelib_ab_day_names_uk_UA, + 8, + 9 ); /***** LOCALE END uk_UA *****/ @@ -1639,7 +1745,9 @@ MY_LOCALE my_locale_ur_PK &my_locale_typelib_month_names_ur_PK, &my_locale_typelib_ab_month_names_ur_PK, &my_locale_typelib_day_names_ur_PK, - &my_locale_typelib_ab_day_names_ur_PK + &my_locale_typelib_ab_day_names_ur_PK, + 6, + 6 ); /***** LOCALE END ur_PK *****/ @@ -1669,7 +1777,9 @@ MY_LOCALE my_locale_vi_VN &my_locale_typelib_month_names_vi_VN, &my_locale_typelib_ab_month_names_vi_VN, &my_locale_typelib_day_names_vi_VN, - &my_locale_typelib_ab_day_names_vi_VN + &my_locale_typelib_ab_day_names_vi_VN, + 16, + 11 ); /***** LOCALE END vi_VN *****/ @@ -1699,7 +1809,9 @@ MY_LOCALE my_locale_zh_CN &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, - &my_locale_typelib_ab_day_names_zh_CN + &my_locale_typelib_ab_day_names_zh_CN, + 3, + 3 ); /***** LOCALE END zh_CN *****/ @@ -1729,7 +1841,9 @@ MY_LOCALE my_locale_zh_TW &my_locale_typelib_month_names_zh_TW, &my_locale_typelib_ab_month_names_zh_TW, &my_locale_typelib_day_names_zh_TW, - &my_locale_typelib_ab_day_names_zh_TW + &my_locale_typelib_ab_day_names_zh_TW, + 3, + 2 ); /***** LOCALE END zh_TW *****/ @@ -1743,7 +1857,9 @@ MY_LOCALE my_locale_ar_DZ &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_DZ *****/ @@ -1757,7 +1873,9 @@ MY_LOCALE my_locale_ar_EG &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_EG *****/ @@ -1771,7 +1889,9 @@ MY_LOCALE my_locale_ar_IN &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_IN *****/ @@ -1785,7 +1905,9 @@ MY_LOCALE my_locale_ar_IQ &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_IQ *****/ @@ -1799,7 +1921,9 @@ MY_LOCALE my_locale_ar_KW &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_KW *****/ @@ -1813,7 +1937,9 @@ MY_LOCALE my_locale_ar_LB &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, - &my_locale_typelib_ab_day_names_ar_JO + &my_locale_typelib_ab_day_names_ar_JO, + 12, + 8 ); /***** LOCALE END ar_LB *****/ @@ -1827,7 +1953,9 @@ MY_LOCALE my_locale_ar_LY &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_LY *****/ @@ -1841,7 +1969,9 @@ MY_LOCALE my_locale_ar_MA &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_MA *****/ @@ -1855,7 +1985,9 @@ MY_LOCALE my_locale_ar_OM &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_OM *****/ @@ -1869,7 +2001,9 @@ MY_LOCALE my_locale_ar_QA &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_QA *****/ @@ -1883,7 +2017,9 @@ MY_LOCALE my_locale_ar_SD &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_SD *****/ @@ -1897,7 +2033,9 @@ MY_LOCALE my_locale_ar_TN &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_TN *****/ @@ -1911,7 +2049,9 @@ MY_LOCALE my_locale_ar_YE &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, - &my_locale_typelib_ab_day_names_ar_BH + &my_locale_typelib_ab_day_names_ar_BH, + 6, + 8 ); /***** LOCALE END ar_YE *****/ @@ -1925,7 +2065,9 @@ MY_LOCALE my_locale_de_BE &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, - &my_locale_typelib_ab_day_names_de_DE + &my_locale_typelib_ab_day_names_de_DE, + 9, + 10 ); /***** LOCALE END de_BE *****/ @@ -1939,7 +2081,9 @@ MY_LOCALE my_locale_de_CH &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, - &my_locale_typelib_ab_day_names_de_DE + &my_locale_typelib_ab_day_names_de_DE, + 9, + 10 ); /***** LOCALE END de_CH *****/ @@ -1953,7 +2097,9 @@ MY_LOCALE my_locale_de_LU &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, - &my_locale_typelib_ab_day_names_de_DE + &my_locale_typelib_ab_day_names_de_DE, + 9, + 10 ); /***** LOCALE END de_LU *****/ @@ -1967,7 +2113,9 @@ MY_LOCALE my_locale_en_AU &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_AU *****/ @@ -1981,7 +2129,9 @@ MY_LOCALE my_locale_en_CA &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_CA *****/ @@ -1995,7 +2145,9 @@ MY_LOCALE my_locale_en_GB &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_GB *****/ @@ -2009,7 +2161,9 @@ MY_LOCALE my_locale_en_IN &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_IN *****/ @@ -2023,7 +2177,9 @@ MY_LOCALE my_locale_en_NZ &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_NZ *****/ @@ -2037,7 +2193,9 @@ MY_LOCALE my_locale_en_PH &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_PH *****/ @@ -2051,7 +2209,9 @@ MY_LOCALE my_locale_en_ZA &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_ZA *****/ @@ -2065,7 +2225,9 @@ MY_LOCALE my_locale_en_ZW &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, - &my_locale_typelib_ab_day_names_en_US + &my_locale_typelib_ab_day_names_en_US, + 9, + 9 ); /***** LOCALE END en_ZW *****/ @@ -2079,7 +2241,9 @@ MY_LOCALE my_locale_es_AR &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_AR *****/ @@ -2093,7 +2257,9 @@ MY_LOCALE my_locale_es_BO &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_BO *****/ @@ -2107,7 +2273,9 @@ MY_LOCALE my_locale_es_CL &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_CL *****/ @@ -2121,7 +2289,9 @@ MY_LOCALE my_locale_es_CO &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_CO *****/ @@ -2135,7 +2305,9 @@ MY_LOCALE my_locale_es_CR &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_CR *****/ @@ -2149,7 +2321,9 @@ MY_LOCALE my_locale_es_DO &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_DO *****/ @@ -2163,7 +2337,9 @@ MY_LOCALE my_locale_es_EC &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_EC *****/ @@ -2177,7 +2353,9 @@ MY_LOCALE my_locale_es_GT &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_GT *****/ @@ -2191,7 +2369,9 @@ MY_LOCALE my_locale_es_HN &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_HN *****/ @@ -2205,7 +2385,9 @@ MY_LOCALE my_locale_es_MX &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_MX *****/ @@ -2219,7 +2401,9 @@ MY_LOCALE my_locale_es_NI &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_NI *****/ @@ -2233,7 +2417,9 @@ MY_LOCALE my_locale_es_PA &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_PA *****/ @@ -2247,7 +2433,9 @@ MY_LOCALE my_locale_es_PE &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_PE *****/ @@ -2261,7 +2449,9 @@ MY_LOCALE my_locale_es_PR &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_PR *****/ @@ -2275,7 +2465,9 @@ MY_LOCALE my_locale_es_PY &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_PY *****/ @@ -2289,7 +2481,9 @@ MY_LOCALE my_locale_es_SV &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_SV *****/ @@ -2303,7 +2497,9 @@ MY_LOCALE my_locale_es_US &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_US *****/ @@ -2317,7 +2513,9 @@ MY_LOCALE my_locale_es_UY &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_UY *****/ @@ -2331,7 +2529,9 @@ MY_LOCALE my_locale_es_VE &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, - &my_locale_typelib_ab_day_names_es_ES + &my_locale_typelib_ab_day_names_es_ES, + 10, + 9 ); /***** LOCALE END es_VE *****/ @@ -2345,7 +2545,9 @@ MY_LOCALE my_locale_fr_BE &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, - &my_locale_typelib_ab_day_names_fr_FR + &my_locale_typelib_ab_day_names_fr_FR, + 9, + 8 ); /***** LOCALE END fr_BE *****/ @@ -2359,7 +2561,9 @@ MY_LOCALE my_locale_fr_CA &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, - &my_locale_typelib_ab_day_names_fr_FR + &my_locale_typelib_ab_day_names_fr_FR, + 9, + 8 ); /***** LOCALE END fr_CA *****/ @@ -2373,7 +2577,9 @@ MY_LOCALE my_locale_fr_CH &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, - &my_locale_typelib_ab_day_names_fr_FR + &my_locale_typelib_ab_day_names_fr_FR, + 9, + 8 ); /***** LOCALE END fr_CH *****/ @@ -2387,7 +2593,9 @@ MY_LOCALE my_locale_fr_LU &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, - &my_locale_typelib_ab_day_names_fr_FR + &my_locale_typelib_ab_day_names_fr_FR, + 9, + 8 ); /***** LOCALE END fr_LU *****/ @@ -2401,7 +2609,9 @@ MY_LOCALE my_locale_it_IT &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, - &my_locale_typelib_ab_day_names_it_CH + &my_locale_typelib_ab_day_names_it_CH, + 9, + 9 ); /***** LOCALE END it_IT *****/ @@ -2415,7 +2625,9 @@ MY_LOCALE my_locale_nl_BE &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, - &my_locale_typelib_ab_day_names_nl_NL + &my_locale_typelib_ab_day_names_nl_NL, + 9, + 9 ); /***** LOCALE END nl_BE *****/ @@ -2429,7 +2641,9 @@ MY_LOCALE my_locale_no_NO &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, - &my_locale_typelib_ab_day_names_nb_NO + &my_locale_typelib_ab_day_names_nb_NO, + 9, + 7 ); /***** LOCALE END no_NO *****/ @@ -2443,7 +2657,9 @@ MY_LOCALE my_locale_sv_FI &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, - &my_locale_typelib_ab_day_names_sv_SE + &my_locale_typelib_ab_day_names_sv_SE, + 9, + 7 ); /***** LOCALE END sv_FI *****/ @@ -2457,7 +2673,9 @@ MY_LOCALE my_locale_zh_HK &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, - &my_locale_typelib_ab_day_names_zh_CN + &my_locale_typelib_ab_day_names_zh_CN, + 3, + 3 ); /***** LOCALE END zh_HK *****/ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 50a55c3a587..68bb7d81e6b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -976,8 +976,24 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->set_time(); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= global_query_id; - if (command != COM_STATISTICS && command != COM_PING) + + switch( command ) { + /* Ignore these statements. */ + case COM_STATISTICS: + case COM_PING: + break; + /* Only increase id on these statements but don't count them. */ + case COM_STMT_PREPARE: + case COM_STMT_CLOSE: + case COM_STMT_RESET: next_query_id(); + break; + /* Increase id and count all other statements. */ + default: + statistic_increment(thd->status_var.questions, &LOCK_status); + next_query_id(); + } + thread_running++; /* TODO: set thd->lex->sql_command to SQLCOM_END here */ VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -1248,6 +1264,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_length= length; thd->query= beginning_of_next_stmt; + /* + Count each statement from the client. + */ + statistic_increment(thd->status_var.questions, &LOCK_status); thd->query_id= next_query_id(); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ @@ -5497,9 +5517,10 @@ bool check_stack_overrun(THD *thd, long margin, if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (my_thread_stack_size - margin)) { - sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE), - stack_used,my_thread_stack_size,margin); - my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0)); + char ebuff[MYSQL_ERRMSG_SIZE]; + my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE), + stack_used, my_thread_stack_size, margin); + my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR)); thd->fatal_error(); return 1; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5ed64ea8fd5..ae55c194c3c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 MySQL AB +/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4233,9 +4233,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, after the change as before. Thus we can reply ok immediately without any changes at all. */ - DBUG_RETURN(fast_end_partition(thd, ULL(0), ULL(0), - table, NULL, - TRUE, NULL, FALSE)); + *fast_alter_partition= TRUE; + DBUG_RETURN(FALSE); } else if (new_part_no > curr_part_no) { @@ -5304,8 +5303,8 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_LEN]; - char normal_path[FN_LEN]; + char tmp_path[FN_REFLEN]; + char normal_path[FN_REFLEN]; List_iterator<partition_element> part_it(part_info->partitions); uint temp_partitions= part_info->temp_partitions.elements; uint no_elements= part_info->partitions.elements; @@ -5516,7 +5515,7 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt) partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL; - char shadow_path[FN_LEN]; + char shadow_path[FN_REFLEN]; DBUG_ENTER("write_log_drop_shadow_frm"); build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt); @@ -5559,8 +5558,8 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry; - char path[FN_LEN]; - char shadow_path[FN_LEN]; + char path[FN_REFLEN]; + char shadow_path[FN_REFLEN]; DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry; DBUG_ENTER("write_log_rename_frm"); @@ -5610,8 +5609,8 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry; - char tmp_path[FN_LEN]; - char path[FN_LEN]; + char tmp_path[FN_REFLEN]; + char path[FN_REFLEN]; uint next_entry= 0; DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry; DBUG_ENTER("write_log_drop_partition"); @@ -5669,8 +5668,8 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL; - char tmp_path[FN_LEN]; - char path[FN_LEN]; + char tmp_path[FN_REFLEN]; + char path[FN_REFLEN]; uint next_entry= 0; DBUG_ENTER("write_log_add_change_partition"); @@ -5723,8 +5722,8 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry; - char path[FN_LEN]; - char shadow_path[FN_LEN]; + char path[FN_REFLEN]; + char shadow_path[FN_REFLEN]; DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry; uint next_entry= 0; DBUG_ENTER("write_log_final_change_partition"); @@ -6679,6 +6678,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, uint32 max_endpoint_val; get_endpoint_func get_endpoint; uint field_len= field->pack_length_in_rec(); + part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; if (part_info->part_type == RANGE_PARTITION) { @@ -6699,7 +6699,6 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, max_endpoint_val= part_info->no_list_values; part_iter->get_next= get_next_partition_id_list; part_iter->part_info= part_info; - part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; if (max_endpoint_val == 0) { /* @@ -6761,7 +6760,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, store_key_image_to_rec(field, max_value, field_len); bool include_endp= !test(flags & NEAR_MAX); part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp); - if (part_iter->part_nums.start == part_iter->part_nums.end && + if (part_iter->part_nums.start >= part_iter->part_nums.end && !part_iter->ret_null_part) return 0; /* No partitions */ } @@ -6939,7 +6938,7 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info, uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter) { - if (part_iter->part_nums.cur == part_iter->part_nums.end) + if (part_iter->part_nums.cur >= part_iter->part_nums.end) { part_iter->part_nums.cur= part_iter->part_nums.start; return NOT_A_PARTITION_ID; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 13b2bfef24d..60f205ec8e8 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -751,21 +751,22 @@ static bool plugin_add(MEM_ROOT *tmp_root, tmp.name.length= name_len; tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; - if (!test_plugin_options(tmp_root, &tmp, argc, argv, true)) + if (test_plugin_options(tmp_root, &tmp, argc, argv, true)) + tmp.state= PLUGIN_IS_DISABLED; + + if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) { - if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) + plugin_array_version++; + if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) { - plugin_array_version++; - if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) - { - init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); - DBUG_RETURN(FALSE); - } - tmp_plugin_ptr->state= PLUGIN_IS_FREED; + init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); + DBUG_RETURN(FALSE); } - mysql_del_sys_var_chain(tmp.system_vars); - goto err; + tmp_plugin_ptr->state= PLUGIN_IS_FREED; } + mysql_del_sys_var_chain(tmp.system_vars); + goto err; + /* plugin was disabled */ plugin_dl_del(dl); DBUG_RETURN(FALSE); @@ -1137,6 +1138,9 @@ int plugin_init(int *argc, char **argv, int flags) { for (plugin= *builtins; plugin->info; plugin++) { + if (opt_ignore_builtin_innodb && + !my_strcasecmp(&my_charset_latin1, plugin->name, "InnoDB")) + continue; /* by default, ndbcluster and federated are disabled */ def_enabled= my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 && @@ -1145,11 +1149,12 @@ int plugin_init(int *argc, char **argv, int flags) tmp.plugin= plugin; tmp.name.str= (char *)plugin->name; tmp.name.length= strlen(plugin->name); - + tmp.state= 0; free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled)) - continue; - + tmp.state= PLUGIN_IS_DISABLED; + else + tmp.state= PLUGIN_IS_UNINITIALIZED; if (register_builtin(plugin, &tmp, &plugin_ptr)) goto err_unlock; @@ -1159,7 +1164,8 @@ int plugin_init(int *argc, char **argv, int flags) my_strcasecmp(&my_charset_latin1, plugin->name, "CSV")) continue; - if (plugin_initialize(plugin_ptr)) + if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED && + plugin_initialize(plugin_ptr)) goto err_unlock; /* @@ -1246,8 +1252,6 @@ static bool register_builtin(struct st_mysql_plugin *plugin, struct st_plugin_int **ptr) { DBUG_ENTER("register_builtin"); - - tmp->state= PLUGIN_IS_UNINITIALIZED; tmp->ref_count= 0; tmp->plugin_dl= 0; @@ -1296,7 +1300,7 @@ bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin) if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL, true)) goto end; - + tmp.state= PLUGIN_IS_UNINITIALIZED; if ((result= register_builtin(plugin, &tmp, &ptr))) mysql_del_sys_var_chain(tmp.system_vars); @@ -1555,7 +1559,8 @@ void plugin_shutdown(void) We loop through all plugins and call deinit() if they have one. */ for (i= 0; i < count; i++) - if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED))) + if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED | + PLUGIN_IS_DISABLED))) { sql_print_information("Plugin '%s' will be forced to shutdown", plugins[i]->name.str); diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index e8f2cb6ee5e..8ae38d58845 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -54,6 +54,7 @@ typedef struct st_mysql_show_var SHOW_VAR; #define PLUGIN_IS_UNINITIALIZED 4 #define PLUGIN_IS_READY 8 #define PLUGIN_IS_DYING 16 +#define PLUGIN_IS_DISABLED 32 /* A handle for the dynamic library containing a plugin or plugins. */ diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index c62cf6401ba..cb5b3722559 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -552,8 +552,8 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) The order of these fields is set by the query_profile_statistics_info array. */ - table->field[0]->store((ulonglong) query->profiling_query_id); - table->field[1]->store((ulonglong) seq); /* the step in the sequence */ + table->field[0]->store((ulonglong) query->profiling_query_id, TRUE); + table->field[1]->store((ulonglong) seq, TRUE); /* the step in the sequence */ /* This entry, n, has a point in time, T(n), and a status phrase, S(n). The status phrase S(n) describes the period of time that begins at diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index eac7a50417a..81db5469891 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -63,7 +63,7 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, ulong event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN; int4store(header + SERVER_ID_OFFSET, server_id); int4store(header + EVENT_LEN_OFFSET, event_len); - int2store(header + FLAGS_OFFSET, 0); + int2store(header + FLAGS_OFFSET, LOG_EVENT_ARTIFICIAL_F); // TODO: check what problems this may cause and fix them int4store(header + LOG_POS_OFFSET, 0); @@ -257,6 +257,17 @@ bool purge_error_message(THD* thd, int res) } +/** + Execute a PURGE BINARY LOGS TO <log> command. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param to_log Name of the last log to purge. + + @retval FALSE success + @retval TRUE failure +*/ bool purge_master_logs(THD* thd, const char* to_log) { char search_file_name[FN_REFLEN]; @@ -273,6 +284,17 @@ bool purge_master_logs(THD* thd, const char* to_log) } +/** + Execute a PURGE BINARY LOGS BEFORE <date> command. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param purge_time Date before which logs should be purged. + + @retval FALSE success + @retval TRUE failure +*/ bool purge_master_logs_before_date(THD* thd, time_t purge_time) { if (!mysql_bin_log.is_open()) @@ -765,6 +787,20 @@ err: DBUG_VOID_RETURN; } + +/** + Execute a START SLAVE statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param mi Pointer to Master_info object for the slave's IO thread. + + @param net_report If true, saves the exit status into thd->main_da. + + @retval 0 success + @retval 1 error +*/ int start_slave(THD* thd , Master_info* mi, bool net_report) { int slave_errno= 0; @@ -890,6 +926,19 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) } +/** + Execute a STOP SLAVE statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param mi Pointer to Master_info object for the slave's IO thread. + + @param net_report If true, saves the exit status into thd->main_da. + + @retval 0 success + @retval 1 error +*/ int stop_slave(THD* thd, Master_info* mi, bool net_report ) { DBUG_ENTER("stop_slave"); @@ -942,20 +991,17 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) } -/* - Remove all relay logs and start replication from the start - - SYNOPSIS - reset_slave() - thd Thread handler - mi Master info for the slave +/** + Execute a RESET SLAVE statement. - RETURN - 0 ok - 1 error -*/ + @param thd Pointer to THD object of the client thread executing the + statement. + @param mi Pointer to Master_info object for the slave. + @retval 0 success + @retval 1 error +*/ int reset_slave(THD *thd, Master_info* mi) { MY_STAT stat_area; @@ -1070,6 +1116,18 @@ void kill_zombie_dump_threads(uint32 slave_server_id) } +/** + Execute a CHANGE MASTER statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @param mi Pointer to Master_info object belonging to the slave's IO + thread. + + @retval FALSE success + @retval TRUE error +*/ bool change_master(THD* thd, Master_info* mi) { int thread_mask; @@ -1283,6 +1341,16 @@ bool change_master(THD* thd, Master_info* mi) DBUG_RETURN(FALSE); } + +/** + Execute a RESET MASTER statement. + + @param thd Pointer to THD object of the client thread executing the + statement. + + @retval 0 success + @retval 1 error +*/ int reset_master(THD* thd) { if (!mysql_bin_log.is_open()) @@ -1312,6 +1380,15 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, } +/** + Execute a SHOW BINLOG EVENTS statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @retval FALSE success + @retval TRUE failure +*/ bool mysql_show_binlog_events(THD* thd) { Protocol *protocol= thd->protocol; @@ -1462,6 +1539,15 @@ err: } +/** + Execute a SHOW MASTER STATUS statement. + + @param thd Pointer to THD object for the client thread executing the + statement. + + @retval FALSE success + @retval TRUE failure +*/ bool show_binlog_info(THD* thd) { Protocol *protocol= thd->protocol; @@ -1495,18 +1581,15 @@ bool show_binlog_info(THD* thd) } -/* - Send a list of all binary logs to client +/** + Execute a SHOW BINARY LOGS statement. - SYNOPSIS - show_binlogs() - thd Thread specific variable + @param thd Pointer to THD object for the client thread executing the + statement. - RETURN VALUES - FALSE OK - TRUE error + @retval FALSE success + @retval TRUE failure */ - bool show_binlogs(THD* thd) { IO_CACHE *index_file; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 97fba012c08..9dd72ab55ba 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -88,7 +88,6 @@ static store_key *get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part, uchar *key_buff, uint maybe_null); -static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void make_join_readinfo(JOIN *join, ulonglong options); @@ -110,7 +109,7 @@ static COND* substitute_for_best_equal_field(COND *cond, void *table_join_idx); static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top); -static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next); +static bool check_interleaving_with_nj(JOIN_TAB *next); static void restore_prev_nj_state(JOIN_TAB *last); static void reset_nj_counters(List<TABLE_LIST> *join_list); static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, @@ -1670,14 +1669,22 @@ JOIN::exec() (zero_result_cause?zero_result_cause:"No tables used")); else { - result->send_fields(*columns_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); + if (result->send_fields(*columns_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + { + DBUG_VOID_RETURN; + } /* We have to test for 'conds' here as the WHERE may not be constant even if we don't have any tables for prepared statements or if conds uses something like 'rand()'. + If the HAVING clause is either impossible or always true, then + JOIN::having is set to NULL by optimize_cond. + In this case JOIN::exec must check for JOIN::having_value, in the + same way it checks for JOIN::cond_value. */ if (cond_value != Item::COND_FALSE && + having_value != Item::COND_FALSE && (!conds || conds->val_int()) && (!having || having->val_int())) { @@ -1874,7 +1881,7 @@ JOIN::exec() /* Free first data from old join */ curr_join->join_free(); - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -1997,7 +2004,7 @@ JOIN::exec() curr_join->select_distinct=0; } curr_tmp_table->reginfo.lock_type= TL_UNLOCK; - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, curr_join->group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -2587,7 +2594,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (s->dependent & table->map) s->dependent |= table->reginfo.join_tab->dependent; } - if (s->dependent) + if (outer_join & s->table->map) s->table->maybe_null= 1; } /* Catch illegal cross references for outer joins */ @@ -4889,6 +4896,18 @@ greedy_search(JOIN *join, */ join->positions[idx]= best_pos; + /* + Update the interleaving state after extending the current partial plan + with a new table. + We are doing this here because best_extension_by_limited_search reverts + the interleaving state to the one of the non-extended partial plan + on exit. + */ + IF_DBUG(bool is_interleave_error= ) + check_interleaving_with_nj (best_table); + /* This has been already checked by best_extension_by_limited_search */ + DBUG_ASSERT(!is_interleave_error); + /* find the position of 'best_table' in 'join->best_ref' */ best_idx= idx; JOIN_TAB *pos= join->best_ref[best_idx]; @@ -4906,7 +4925,7 @@ greedy_search(JOIN *join, --size_remain; ++idx; - DBUG_EXECUTE("opt", print_plan(join, join->tables, + DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time, "extended");); } while (TRUE); @@ -5064,7 +5083,7 @@ best_extension_by_limited_search(JOIN *join, table_map real_table_bit= s->table->map; if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent) && - (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx || !check_interleaving_with_nj(s))) { double current_record_count, current_read_time; @@ -5210,7 +5229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, { table_map real_table_bit=s->table->map; if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) && - (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx|| !check_interleaving_with_nj(s))) { double records, best; best_access_path(join, s, thd, rest_tables, idx, record_count, @@ -5669,48 +5688,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag) } -static bool -make_simple_join(JOIN *join,TABLE *tmp_table) +/** + @details Initialize a JOIN as a query execution plan + that accesses a single table via a table scan. + + @param parent contains JOIN_TAB and TABLE object buffers for this join + @param tmp_table temporary table + + @retval FALSE success + @retval TRUE error occurred +*/ +bool +JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) { - TABLE **tableptr; - JOIN_TAB *join_tab; - DBUG_ENTER("make_simple_join"); + DBUG_ENTER("JOIN::make_simple_join"); /* Reuse TABLE * and JOIN_TAB if already allocated by a previous call to this function through JOIN::exec (may happen for sub-queries). */ - if (!join->table_reexec) - { - if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->table_reexec= join->table_reexec; - } - if (!join->join_tab_reexec) - { - if (!(join->join_tab_reexec= - (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->join_tab_reexec= join->join_tab_reexec; - } - tableptr= join->table_reexec; - join_tab= join->join_tab_reexec; - - join->join_tab=join_tab; - join->table=tableptr; tableptr[0]=tmp_table; - join->tables=1; - join->const_tables=0; - join->const_table_map=0; - join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count= - join->tmp_table_param.func_count=0; - join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0; - join->first_record=join->sort_and_group=0; - join->send_records=(ha_rows) 0; - join->group=0; - join->row_limit=join->unit->select_limit_cnt; - join->do_send_rows = (join->row_limit) ? 1 : 0; + if (!parent->join_tab_reexec && + !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) + DBUG_RETURN(TRUE); /* purecov: inspected */ + + join_tab= parent->join_tab_reexec; + table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table; + tables= 1; + const_tables= 0; + const_table_map= 0; + tmp_table_param.field_count= tmp_table_param.sum_func_count= + tmp_table_param.func_count= 0; + tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; + first_record= sort_and_group=0; + send_records= (ha_rows) 0; + group= 0; + row_limit= unit->select_limit_cnt; + do_send_rows= row_limit ? 1 : 0; join_tab->cache.buff=0; /* No caching */ join_tab->table=tmp_table; @@ -5727,7 +5740,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join_tab->ref.key = -1; join_tab->not_used_in_distinct=0; join_tab->read_first_record= join_init_read_record; - join_tab->join=join; + join_tab->join= this; join_tab->ref.key_parts= 0; bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); tmp_table->status=0; @@ -8790,9 +8803,6 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) the partial join order. @endverbatim - @param join Join being processed - @param last_tab Last table in current partial join order (this function is - not called for empty partial join orders) @param next_tab Table we're going to extend the current partial join with @retval @@ -8802,10 +8812,10 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) TRUE Requested join order extension not allowed. */ -static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab) +static bool check_interleaving_with_nj(JOIN_TAB *next_tab) { TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding; - JOIN *join= last_tab->join; + JOIN *join= next_tab->join; if (join->cur_embedding_map & ~next_tab->embedding_map) { @@ -13866,6 +13876,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count) length=0; for (i=0 ; i < table_count ; i++) { + bool have_bit_fields= FALSE; uint null_fields=0,used_fields; Field **f_ptr,*field; MY_BITMAP *read_set= tables[i].table->read_set; @@ -13880,13 +13891,16 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count) length+=field->fill_cache_field(copy); if (copy->blob_field) (*blob_ptr++)=copy; - if (field->maybe_null()) + if (field->real_maybe_null()) null_fields++; + if (field->type() == MYSQL_TYPE_BIT && + ((Field_bit*)field)->bit_len) + have_bit_fields= TRUE; copy++; } } /* Copy null bits from table */ - if (null_fields && tables[i].table->s->null_fields) + if (null_fields || have_bit_fields) { /* must copy null bits */ copy->str= tables[i].table->null_flags; copy->length= tables[i].table->s->null_bytes; diff --git a/sql/sql_select.h b/sql/sql_select.h index be159c523e0..7d794b71f4d 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -285,7 +285,11 @@ public: fetching data from a cursor */ bool resume_nested_loop; - table_map const_table_map,found_const_table_map,outer_join; + table_map const_table_map,found_const_table_map; + /* + Bitmap of all inner tables from outer joins + */ + table_map outer_join; ha_rows send_records,found_records,examined_rows,row_limit, select_limit; /** Used to fetch no more than given amount of rows per one @@ -398,9 +402,12 @@ public: cleared only at the end of the execution of the whole query and not caching allocations that occur in repetition at execution time will result in excessive memory usage. + Note: make_simple_join always creates an execution plan that accesses + a single table, thus it is sufficient to have a one-element array for + table_reexec. */ SORT_FIELD *sortorder; // make_unireg_sortorder() - TABLE **table_reexec; // make_simple_join() + TABLE *table_reexec[1]; // make_simple_join() JOIN_TAB *join_tab_reexec; // make_simple_join() /* end of allocation caching storage */ @@ -430,7 +437,7 @@ public: exec_tmp_table1= 0; exec_tmp_table2= 0; sortorder= 0; - table_reexec= 0; + table_reexec[0]= 0; join_tab_reexec= 0; thd= thd_arg; sum_funcs= sum_funcs2= 0; @@ -522,6 +529,8 @@ public: return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex)); } +private: + bool make_simple_join(JOIN *join, TABLE *tmp_table); }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 28e8c028362..3c4dc103ddd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -124,6 +124,9 @@ static my_bool show_plugins(THD *thd, plugin_ref plugin, case PLUGIN_IS_READY: table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs); break; + case PLUGIN_IS_DISABLED: + table->field[2]->store(STRING_WITH_LEN("DISABLED"), cs); + break; default: DBUG_ASSERT(0); } @@ -471,6 +474,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db, if (wild && !wild[0]) wild=0; + bzero((char*) &table_list,sizeof(table_list)); if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0)))) @@ -993,7 +997,7 @@ static bool get_field_default_value(THD *thd, TABLE *table, { bool has_default; bool has_now_default; - + enum enum_field_types field_type= field->type(); /* We are using CURRENT_TIMESTAMP instead of NOW because it is more standard @@ -1001,7 +1005,7 @@ static bool get_field_default_value(THD *thd, TABLE *table, has_now_default= table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_UN_FIELD; - has_default= (field->type() != FIELD_TYPE_BLOB && + has_default= (field_type != FIELD_TYPE_BLOB && !(field->flags & NO_DEFAULT_VALUE_FLAG) && field->unireg_check != Field::NEXT_NUMBER && !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) @@ -1016,7 +1020,19 @@ static bool get_field_default_value(THD *thd, TABLE *table, { // Not null by default char tmp[MAX_FIELD_WIDTH]; String type(tmp, sizeof(tmp), field->charset()); - field->val_str(&type); + if (field_type == MYSQL_TYPE_BIT) + { + longlong dec= field->val_int(); + char *ptr= longlong2str(dec, tmp + 2, 2); + uint32 length= (uint32) (ptr - tmp); + tmp[0]= 'b'; + tmp[1]= '\''; + tmp[length]= '\''; + type.length(length + 1); + quoted= 0; + } + else + field->val_str(&type); if (type.length()) { String def_val; @@ -3577,6 +3593,11 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, (share->transactional == HA_CHOICE_YES ? "1" : "0"), NullS); } + if (share->key_block_size) + { + ptr= strmov(ptr, " KEY_BLOCK_SIZE="); + ptr= longlong10_to_str(share->key_block_size, ptr, 10); + } #ifdef WITH_PARTITION_STORAGE_ENGINE if (is_partitioned) ptr= strmov(ptr, " partitioned"); @@ -3913,6 +3934,25 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, handlerton *default_type= ha_default_handlerton(thd); DBUG_ENTER("iter_schema_engines"); + + /* Disabled plugins */ + if (plugin_state(plugin) != PLUGIN_IS_READY) + { + + struct st_mysql_plugin *plug= plugin_decl(plugin); + if (!(wild && wild[0] && + wild_case_compare(scs, plug->name,wild))) + { + restore_record(table, s->default_values); + table->field[0]->store(plug->name, strlen(plug->name), scs); + table->field[1]->store(C_STRING_WITH_LEN("NO"), scs); + table->field[2]->store(plug->descr, strlen(plug->descr), scs); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + } + DBUG_RETURN(0); + } + if (!(hton->flags & HTON_HIDDEN)) { LEX_STRING *name= plugin_name(plugin); @@ -3933,10 +3973,13 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, strlen(plugin_decl(plugin)->descr), scs); tmp= &yesno[test(hton->commit)]; table->field[3]->store(tmp->str, tmp->length, scs); + table->field[3]->set_notnull(); tmp= &yesno[test(hton->prepare)]; table->field[4]->store(tmp->str, tmp->length, scs); + table->field[4]->set_notnull(); tmp= &yesno[test(hton->savepoint_set)]; table->field[5]->store(tmp->str, tmp->length, scs); + table->field[5]->set_notnull(); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -3947,8 +3990,12 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) { - return plugin_foreach(thd, iter_schema_engines, - MYSQL_STORAGE_ENGINE_PLUGIN, tables->table); + DBUG_ENTER("fill_schema_engines"); + if (plugin_foreach_with_mask(thd, iter_schema_engines, + MYSQL_STORAGE_ENGINE_PLUGIN, + ~PLUGIN_IS_FREED, tables->table)) + DBUG_RETURN(1); + DBUG_RETURN(0); } @@ -6145,9 +6192,9 @@ ST_FIELD_INFO engines_fields_info[]= {"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine", SKIP_OPEN_TABLE}, {"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support", SKIP_OPEN_TABLE}, {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", SKIP_OPEN_TABLE}, - {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 0, "Transactions", SKIP_OPEN_TABLE}, - {"XA", 3, MYSQL_TYPE_STRING, 0, 0, "XA", SKIP_OPEN_TABLE}, - {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 0, "Savepoints", SKIP_OPEN_TABLE}, + {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 1, "Transactions", SKIP_OPEN_TABLE}, + {"XA", 3, MYSQL_TYPE_STRING, 0, 1, "XA", SKIP_OPEN_TABLE}, + {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 1, "Savepoints", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; diff --git a/sql/sql_show.h b/sql/sql_show.h index 3baaef00a7d..fa067a46033 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ec35616bc89..aa2a5739f17 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -114,6 +114,30 @@ uint filename_to_tablename(const char *from, char *to, uint to_length) } +/** + Check if given string begins with "#mysql50#" prefix, cut it if so. + + @param from string to check and cut + @param to[out] buffer for result string + @param to_length its size + + @retval + 0 no prefix found + @retval + non-0 result string length +*/ + +uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length) +{ + if (from[0] == '#' && + !strncmp(from, MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH)) + return (uint) (strmake(to, from + MYSQL50_TABLE_NAME_PREFIX_LENGTH, + to_length - 1) - to); + return 0; +} + + /* Translate a table name to a file name (WL #1324). @@ -133,11 +157,8 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) DBUG_ENTER("tablename_to_filename"); DBUG_PRINT("enter", ("from '%s'", from)); - if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX, - MYSQL50_TABLE_NAME_PREFIX_LENGTH)) - DBUG_RETURN((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH, - to_length-1) - - (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH))); + if ((length= check_n_cut_mysql50_prefix(from, to, to_length))) + DBUG_RETURN(length); length= strconvert(system_charset_info, from, &my_charset_filename, to, to_length, &errors); if (check_if_legal_tablename(to) && @@ -3111,10 +3132,12 @@ static bool prepare_blob_field(THD *thd, Create_field *sql_field) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, warn_buff); } - + if ((sql_field->flags & BLOB_FLAG) && sql_field->length) { - if (sql_field->sql_type == MYSQL_TYPE_BLOB) + if (sql_field->sql_type == FIELD_TYPE_BLOB || + sql_field->sql_type == FIELD_TYPE_TINY_BLOB || + sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB) { /* The user has given a length to the blob column */ sql_field->sql_type= get_blob_type_from_length(sql_field->length); @@ -3425,14 +3448,6 @@ bool mysql_create_table_no_lock(THD *thd, } else { - #ifdef FN_DEVCHAR - /* check if the table name contains FN_DEVCHAR when defined */ - if (strchr(alias, FN_DEVCHAR)) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), alias); - DBUG_RETURN(TRUE); - } -#endif path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext, internal_tmp_table ? FN_IS_TMP : 0); } @@ -4319,6 +4334,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, table->table=0; // For query cache if (protocol->write()) goto err; + thd->main_da.reset_diagnostics_area(); continue; /* purecov: end */ } @@ -4419,8 +4435,8 @@ send_result_message: switch (result_code) { case HA_ADMIN_NOT_IMPLEMENTED: { - char buf[ERRMSGSIZE+20]; - uint length=my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length=my_snprintf(buf, sizeof(buf), ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4429,8 +4445,8 @@ send_result_message: case HA_ADMIN_NOT_BASE_TABLE: { - char buf[ERRMSGSIZE+20]; - uint length= my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length= my_snprintf(buf, sizeof(buf), ER(ER_BAD_TABLE_ERROR), table_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4557,11 +4573,12 @@ send_result_message: case HA_ADMIN_NEEDS_UPGRADE: case HA_ADMIN_NEEDS_ALTER: { - char buf[ERRMSGSIZE]; + char buf[MYSQL_ERRMSG_SIZE]; uint length; protocol->store(STRING_WITH_LEN("error"), system_charset_info); - length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name); + length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE), + table->table_name); protocol->store(buf, length, system_charset_info); fatal_error=1; break; @@ -4569,8 +4586,8 @@ send_result_message: default: // Probably HA_ADMIN_INTERNAL_ERROR { - char buf[ERRMSGSIZE+20]; - uint length=my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length=my_snprintf(buf, sizeof(buf), "Unknown - internal error %d during operation", result_code); protocol->store(STRING_WITH_LEN("error"), system_charset_info); @@ -4967,6 +4984,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, dst_path); /* purecov: inspected */ goto err; /* purecov: inspected */ } + thd->thread_specific_used= TRUE; } else if (err) { @@ -5867,7 +5885,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (key_info->flags & HA_USES_BLOCK_SIZE) key_create_info.block_size= key_info->block_size; if (key_info->flags & HA_USES_PARSER) - key_create_info.parser_name= *key_info->parser_name; + key_create_info.parser_name= *plugin_name(key_info->parser); if (key_info->flags & HA_SPATIAL) key_type= Key::SPATIAL; diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 01363714484..78932396efe 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -513,7 +513,7 @@ Next alarm time: %lu\n", fprintf(stdout,"\nBegin safemalloc memory dump:\n"); // tag needed for test suite TERMINATE(stdout, 1); // Write malloc information fprintf(stdout,"\nEnd safemalloc memory dump.\n"); - + fflush(stdout); #ifdef HAVE_MALLINFO struct mallinfo info= mallinfo(); printf("\nMemory status:\n\ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 5c8b1d96646..108d5095691 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1368,15 +1368,27 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root)) goto err_with_lex_cleanup; - +#ifndef DBUG_OFF /* Let us check that we correctly update trigger definitions when we rename tables with triggers. + + In special cases like "RENAME TABLE `#mysql50#somename` TO `somename`" + or "ALTER DATABASE `#mysql50#somename` UPGRADE DATA DIRECTORY NAME" + we might be given table or database name with "#mysql50#" prefix (and + trigger's definiton contains un-prefixed version of the same name). + To remove this prefix we use check_n_cut_mysql50_prefix(). */ - DBUG_ASSERT(!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) && - !my_strcasecmp(table_alias_charset, lex.query_tables->table_name, - table_name)); + char fname[NAME_LEN + 1]; + DBUG_ASSERT((!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) || + (check_n_cut_mysql50_prefix(db, fname, sizeof(fname)) && + !my_strcasecmp(table_alias_charset, lex.query_tables->db, fname))) && + (!my_strcasecmp(table_alias_charset, lex.query_tables->table_name, + table_name) || + (check_n_cut_mysql50_prefix(table_name, fname, sizeof(fname)) && + !my_strcasecmp(table_alias_charset, lex.query_tables->table_name, fname)))); +#endif if (names_only) { lex_end(&lex); @@ -1692,7 +1704,8 @@ end: (change name of table in triggers' definitions). @param thd Thread context - @param db_name Database of subject table + @param old_db_name Old database of subject table + @param new_db_name New database of subject table @param old_table_name Old subject table's name @param new_table_name New subject table's name @@ -1704,7 +1717,8 @@ end: bool Table_triggers_list::change_table_name_in_triggers(THD *thd, - const char *db_name, + const char *old_db_name, + const char *new_db_name, LEX_STRING *old_table_name, LEX_STRING *new_table_name) { @@ -1757,11 +1771,11 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, if (thd->is_fatal_error) return TRUE; /* OOM */ - if (save_trigger_file(this, db_name, new_table_name->str)) + if (save_trigger_file(this, new_db_name, new_table_name->str)) return TRUE; - if (rm_trigger_file(path_buff, db_name, old_table_name->str)) + if (rm_trigger_file(path_buff, old_db_name, old_table_name->str)) { - (void) rm_trigger_file(path_buff, db_name, new_table_name->str); + (void) rm_trigger_file(path_buff, new_db_name, new_table_name->str); return TRUE; } return FALSE; @@ -1772,7 +1786,8 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, Iterate though Table_triggers_list::names_list list and update .TRN files after renaming triggers' subject table. - @param db_name Database of subject table + @param old_db_name Old database of subject table + @param new_db_name New database of subject table @param new_table_name New subject table's name @param stopper Pointer to Table_triggers_list::names_list at which we should stop updating. @@ -1785,7 +1800,8 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, */ LEX_STRING* -Table_triggers_list::change_table_name_in_trignames(const char *db_name, +Table_triggers_list::change_table_name_in_trignames(const char *old_db_name, + const char *new_db_name, LEX_STRING *new_table_name, LEX_STRING *stopper) { @@ -1798,7 +1814,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, while ((trigger= it_name++) != stopper) { trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, - db_name, trigger->str, + new_db_name, trigger->str, TRN_EXT, 0); trigname_file.str= trigname_buff; @@ -1807,6 +1823,16 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, (uchar*)&trigname, trigname_file_parameters)) return trigger; + + /* Remove stale .TRN file in case of database upgrade */ + if (old_db_name) + { + if (rm_trigname_file(trigname_buff, old_db_name, trigger->str)) + { + (void) rm_trigname_file(trigname_buff, new_db_name, trigger->str); + return trigger; + } + } } return 0; @@ -1840,6 +1866,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, { TABLE table; bool result= 0; + bool upgrading50to51= FALSE; LEX_STRING *err_trigname; DBUG_ENTER("change_table_name"); @@ -1877,14 +1904,27 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, moving table with them between two schemas raises too many questions. (E.g. what should happen if in new schema we already have trigger with same name ?). + + In case of "ALTER DATABASE `#mysql50#db1` UPGRADE DATA DIRECTORY NAME" + we will be given table name with "#mysql50#" prefix + To remove this prefix we use check_n_cut_mysql50_prefix(). */ if (my_strcasecmp(table_alias_charset, db, new_db)) { - my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); - result= 1; - goto end; + char dbname[NAME_LEN + 1]; + if (check_n_cut_mysql50_prefix(db, dbname, sizeof(dbname)) && + !my_strcasecmp(table_alias_charset, dbname, new_db)) + { + upgrading50to51= TRUE; + } + else + { + my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); + result= 1; + goto end; + } } - if (table.triggers->change_table_name_in_triggers(thd, db, + if (table.triggers->change_table_name_in_triggers(thd, db, new_db, &old_table_name, &new_table_name)) { @@ -1892,7 +1932,8 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, goto end; } if ((err_trigname= table.triggers->change_table_name_in_trignames( - db, &new_table_name, 0))) + upgrading50to51 ? db : NULL, + new_db, &new_table_name, 0))) { /* If we were unable to update one of .TRN files properly we will @@ -1900,16 +1941,17 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, We assume that we will be able to undo our changes without errors (we can't do much if there will be an error anyway). */ - (void) table.triggers->change_table_name_in_trignames(db, - &old_table_name, - err_trigname); - (void) table.triggers->change_table_name_in_triggers(thd, db, - &new_table_name, - &old_table_name); + (void) table.triggers->change_table_name_in_trignames( + upgrading50to51 ? new_db : NULL, db, + &old_table_name, err_trigname); + (void) table.triggers->change_table_name_in_triggers( + thd, db, new_db, + &new_table_name, &old_table_name); result= 1; goto end; } } + end: delete table.triggers; free_root(&table.mem_root, MYF(0)); diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 1b0edf6bea8..f6754a75284 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -146,11 +146,13 @@ public: private: bool prepare_record1_accessors(TABLE *table); - LEX_STRING* change_table_name_in_trignames(const char *db_name, + LEX_STRING* change_table_name_in_trignames(const char *old_db_name, + const char *new_db_name, LEX_STRING *new_table_name, LEX_STRING *stopper); bool change_table_name_in_triggers(THD *thd, - const char *db_name, + const char *old_db_name, + const char *new_db_name, LEX_STRING *old_table_name, LEX_STRING *new_table_name); }; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 2f3282f58f6..fd3036e3d80 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 49ec1a33873..1edd6952a34 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -528,9 +528,11 @@ int mysql_update(THD *thd, init_read_record(&info, thd, table, select, 0, 1, FALSE); updated= found= 0; - /* Generate an error when trying to set a NOT NULL field to NULL. */ - thd->count_cuted_fields= ignore ? CHECK_FIELD_WARN - : CHECK_FIELD_ERROR_FOR_NULL; + /* + Generate an error (in TRADITIONAL mode) or warning + when trying to set a NOT NULL field to NULL. + */ + thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; thd_proc_info(thd, "Updating"); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 93f6ac4391d..7df035bbfc3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/table.cc b/sql/table.cc index 89714e4e47e..17454ffb012 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -400,6 +400,8 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, void free_table_share(TABLE_SHARE *share) { MEM_ROOT mem_root; + uint idx; + KEY *key_info; DBUG_ENTER("free_table_share"); DBUG_PRINT("enter", ("table: %s.%s", share->db.str, share->table_name.str)); DBUG_ASSERT(share->ref_count == 0); @@ -426,6 +428,16 @@ void free_table_share(TABLE_SHARE *share) plugin_unlock(NULL, share->db_plugin); share->db_plugin= NULL; + /* Release fulltext parsers */ + key_info= share->key_info; + for (idx= share->keys; idx; idx--, key_info++) + { + if (key_info->flags & HA_USES_PARSER) + { + plugin_unlock(NULL, key_info->parser); + key_info->flags= 0; + } + } /* We must copy mem_root from share because share is allocated through it */ memcpy((char*) &mem_root, (char*) &share->mem_root, sizeof(mem_root)); free_root(&mem_root, MYF(0)); // Free's share @@ -1416,7 +1428,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, */ if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { - field->part_of_key= share->keys_in_use; + if (field->key_length() == key_part->length && + !(field->flags & BLOB_FLAG)) + field->part_of_key= share->keys_in_use; if (field->part_of_sortkey.is_set(key)) field->part_of_sortkey= share->keys_in_use; } @@ -1941,22 +1955,11 @@ partititon_err: int closefrm(register TABLE *table, bool free_share) { int error=0; - uint idx; - KEY *key_info; DBUG_ENTER("closefrm"); DBUG_PRINT("enter", ("table: 0x%lx", (long) table)); if (table->db_stat) error=table->file->close(); - key_info= table->key_info; - for (idx= table->s->keys; idx; idx--, key_info++) - { - if (key_info->flags & HA_USES_PARSER) - { - plugin_unlock(NULL, key_info->parser); - key_info->flags= 0; - } - } my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR)); table->alias= 0; if (table->field) diff --git a/sql/table.h b/sql/table.h index 77bd7bb9e77..cb53013cd59 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1363,7 +1363,7 @@ struct TABLE_LIST void cleanup_items(); bool placeholder() { - return derived || view || schema_table || create && !table->db_stat || + return derived || view || schema_table || (create && !table->db_stat) || !table; } void print(THD *thd, String *str, enum_query_type query_type); @@ -1691,5 +1691,35 @@ static inline void dbug_tmp_restore_column_map(MY_BITMAP *bitmap, #endif } + +/* + Variant of the above : handle both read and write sets. + Provide for the possiblity of the read set being the same as the write set +*/ +static inline void dbug_tmp_use_all_columns(TABLE *table, + my_bitmap_map **save, + MY_BITMAP *read_set, + MY_BITMAP *write_set) +{ +#ifndef DBUG_OFF + save[0]= read_set->bitmap; + save[1]= write_set->bitmap; + (void) tmp_use_all_columns(table, read_set); + (void) tmp_use_all_columns(table, write_set); +#endif +} + + +static inline void dbug_tmp_restore_column_maps(MY_BITMAP *read_set, + MY_BITMAP *write_set, + my_bitmap_map **old) +{ +#ifndef DBUG_OFF + tmp_restore_column_map(read_set, old[0]); + tmp_restore_column_map(write_set, old[1]); +#endif +} + + size_t max_row_length(TABLE *table, const uchar *data); diff --git a/sql/unireg.cc b/sql/unireg.cc index 9e42aabfef7..da018ebec3d 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -92,8 +92,8 @@ handle_error(uint sql_errno, db_file Handler to use. May be zero, in which case we use create_info->db_type RETURN - 0 ok - 1 error + false ok + true error */ bool mysql_create_frm(THD *thd, const char *file_name, @@ -205,6 +205,24 @@ bool mysql_create_frm(THD *thd, const char *file_name, (create_info->min_rows == 1) && (keys == 0)); int2store(fileinfo+28,key_info_length); + /* + This gives us the byte-position of the character at + (character-position, not byte-position) TABLE_COMMENT_MAXLEN. + The trick here is that character-positions start at 0, so the last + character in a maximum-allowed length string would be at char-pos + MAXLEN-1; charpos MAXLEN will be the position of the terminator. + Consequently, bytepos(charpos(MAXLEN)) should be equal to + comment[length] (which should also be the terminator, or at least + the first byte after the payload in the strict sense). If this is + not so (bytepos(charpos(MAXLEN)) comes /before/ the end of the + string), the string is too long. + + For additional credit, realise that UTF-8 has 1-3 bytes before 6.0, + and 1-4 bytes in 6.0 (6.0 also has UTF-32). This means that the + inlined COMMENT supposedly does not exceed 60 character plus + terminator, vulgo, 181 bytes. + */ + tmp_len= system_charset_info->cset->charpos(system_charset_info, create_info->comment.str, create_info->comment.str + @@ -227,14 +245,6 @@ bool mysql_create_frm(THD *thd, const char *file_name, strmake((char*) forminfo+47, create_info->comment.str ? create_info->comment.str : "", create_info->comment.length); forminfo[46]=(uchar) create_info->comment.length; -#ifdef EXTRA_DEBUG - /* - EXTRA_DEBUG causes strmake() to initialize its buffer behind the - payload with a magic value to detect wrong buffer-sizes. We - explicitly zero that segment again. - */ - memset((char*) forminfo+47 + forminfo[46], 0, 61 - forminfo[46]); -#endif #ifdef WITH_PARTITION_STORAGE_ENGINE if (part_info) { |