diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-09 23:51:51 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-09 23:51:51 +0100 |
commit | 2e11ca36f28133c18b72351d176ee2fd7fcbc465 (patch) | |
tree | 5aefb03db444e9c2856c3aba50f2f28e8fa12772 /sql | |
parent | eff07bf08e29afab76c7688ec063ef6881ee464f (diff) | |
parent | d07b5f1ca295d4eb6eeba0b88c93f04e9e21cb5c (diff) | |
download | mariadb-git-2e11ca36f28133c18b72351d176ee2fd7fcbc465.tar.gz |
mysql-5.1.67 merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_ndbcluster_binlog.cc | 1 | ||||
-rw-r--r-- | sql/hostname.cc | 9 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 22 | ||||
-rw-r--r-- | sql/item_func.cc | 5 | ||||
-rw-r--r-- | sql/item_func.h | 3 | ||||
-rw-r--r-- | sql/log.cc | 7 | ||||
-rw-r--r-- | sql/log_event.cc | 90 | ||||
-rw-r--r-- | sql/log_event.h | 6 | ||||
-rw-r--r-- | sql/mysql_priv.h | 35 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.cc | 50 | ||||
-rw-r--r-- | sql/sql_acl.cc | 84 | ||||
-rw-r--r-- | sql/sql_base.cc | 37 | ||||
-rw-r--r-- | sql/sql_connect.cc | 40 | ||||
-rw-r--r-- | sql/sql_db.cc | 5 | ||||
-rw-r--r-- | sql/sql_insert.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_list.h | 11 | ||||
-rw-r--r-- | sql/sql_profile.cc | 29 | ||||
-rw-r--r-- | sql/sql_profile.h | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 24 |
21 files changed, 321 insertions, 152 deletions
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 0de7cd03176..70b5da17e74 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. + Copyright (c) 2012, 2013, Monty Proram Ab. 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/hostname.cc b/sql/hostname.cc index dfcdd3edd90..cb248150fae 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -215,6 +215,15 @@ char * ip_to_hostname(struct in_addr *in, uint *errors) } my_gethostbyname_r_free(); #else + + DBUG_EXECUTE_IF("addr_fake_ipv4", + { + const char* fake_host= "santa.claus.ipv4.example.com"; + name=my_strdup(fake_host, MYF(0)); + add_hostname(in,name); + DBUG_RETURN(name); + };); + VOID(pthread_mutex_lock(&LOCK_hostname)); if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET))) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c6c09bf0cb5..ec13c82c532 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -3054,6 +3055,15 @@ void Item_func_case::fix_length_and_dec() return; } } + /* + Set cmp_context of all WHEN arguments. This prevents + Item_field::equal_fields_propagator() from transforming a + zerofill argument into a string constant. Such a change would + require rebuilding cmp_items. + */ + for (i= 0; i < ncases; i+= 2) + args[i]->cmp_context= item_cmp_type(left_result_type, + args[i]->result_type()); } if (else_expr_num == -1 || args[else_expr_num]->maybe_null) @@ -4040,6 +4050,16 @@ void Item_func_in::fix_length_and_dec() } } } + /* + Set cmp_context of all arguments. This prevents + Item_field::equal_fields_propagator() from transforming a zerofill integer + argument into a string constant. Such a change would require rebuilding + cmp_itmes. + */ + for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) + { + arg[0]->cmp_context= item_cmp_type(left_result_type, arg[0]->result_type()); + } max_length= 1; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 2fe7e2ec15c..645c9909b93 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -3610,7 +3610,8 @@ longlong Item_func_last_insert_id::val_int() thd->first_successful_insert_id_in_prev_stmt= value; return value; } - return thd->read_first_successful_insert_id_in_prev_stmt(); + return + static_cast<longlong>(thd->read_first_successful_insert_id_in_prev_stmt()); } diff --git a/sql/item_func.h b/sql/item_func.h index 243ecb1ab39..61f7dc2cce3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (c) 2009-2011 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -1060,6 +1060,7 @@ public: const char *func_name() const { return "last_insert_id"; } void fix_length_and_dec() { + unsigned_flag= TRUE; if (arg_count) max_length= args[0]->max_length; } diff --git a/sql/log.cc b/sql/log.cc index e44f8ff3067..252811b8d32 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab 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 @@ -4351,10 +4352,16 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, /* Write pending event to log file or transaction cache */ + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("+d,simulate_file_write_error");}); if (pending->write(file)) { pthread_mutex_unlock(&LOCK_log); set_write_error(thd); + delete pending; + trx_data->set_pending(NULL); + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("-d,simulate_file_write_error");}); DBUG_RETURN(1); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 64424da3e78..27448864cee 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -34,7 +35,7 @@ #include "rpl_utility.h" #include "rpl_record.h" #include <my_dir.h> -#include "sql_show.h" +#include "sql_show.h" // append_identifier #endif /* MYSQL_CLIENT */ @@ -54,6 +55,22 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +/* + Explicit instantiation to unsigned int of template available_buffer + function. +*/ +template unsigned int available_buffer<unsigned int>(const char*, + const char*, + unsigned int); + +/* + Explicit instantiation to unsigned int of template valid_buffer_range + function. +*/ +template bool valid_buffer_range<unsigned int>(unsigned int, + const char*, + const char*, + unsigned int); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); @@ -1285,7 +1302,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, ev = new Rand_log_event(buf, description_event); break; case USER_VAR_EVENT: - ev = new User_var_log_event(buf, description_event); + ev = new User_var_log_event(buf, event_len, description_event); break; case FORMAT_DESCRIPTION_EVENT: ev = new Format_description_log_event(buf, event_len, description_event); @@ -1695,11 +1712,11 @@ beg: int i, end; char buff[512], *pos; pos= buff; - pos+= my_sprintf(buff, (buff, "%s", dec.sign() ? "-" : "")); + pos+= sprintf(buff, "%s", dec.sign() ? "-" : ""); end= ROUND_UP(dec.frac) + ROUND_UP(dec.intg)-1; for (i=0; i < end; i++) - pos+= my_sprintf(pos, (pos, "%09d.", dec.buf[i])); - pos+= my_sprintf(pos, (pos, "%09d", dec.buf[i])); + pos+= sprintf(pos, "%09d.", dec.buf[i]); + pos+= sprintf(pos, "%09d", dec.buf[i]); my_b_printf(file, "%s", buff); my_snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", precision, decimals); @@ -1982,7 +1999,7 @@ void Rows_log_event::print_verbose(IO_CACHE *file, for (const uchar *value= m_rows_buf; value < m_rows_end; ) { size_t length; - my_b_printf(file, "### %s %s.%s\n", + my_b_printf(file, "### %s %`s.%`s\n", sql_command, map->get_db_name(), map->get_table_name()); /* Print the first image */ @@ -2151,7 +2168,7 @@ void Query_log_event::pack_info(THD *thd, Protocol *protocol) { buf.append(STRING_WITH_LEN("use ")); append_identifier(thd, &buf, db, db_len); - buf.append("; "); + buf.append(STRING_WITH_LEN("; ")); } if (query && q_len) buf.append(query, q_len); @@ -2945,17 +2962,11 @@ void Query_log_event::print_query_header(IO_CACHE* file, } else if (db) { - /* Room for expand ` to `` + initial/final ` + \0 */ - char buf[FN_REFLEN*2+3]; - different_db= memcmp(print_event_info->db, db, db_len + 1); if (different_db) memcpy(print_event_info->db, db, db_len + 1); if (db[0] && different_db) - { - my_snprintf(buf, sizeof(buf), "%`s", db); - my_b_printf(file, "use %s%s\n", buf, print_event_info->delimiter); - } + my_b_printf(file, "use %`s%s\n", db, print_event_info->delimiter); } end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); @@ -4583,7 +4594,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, } if (db && db[0] && different_db) - my_b_printf(&cache, "%suse %s%s\n", + my_b_printf(&cache, "%suse %`s%s\n", commented ? "# " : "", db, print_event_info->delimiter); @@ -4635,7 +4646,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, { if (i) my_b_printf(&cache, ","); - my_b_printf(&cache, "%s", field); + my_b_printf(&cache, "%`s", field); field += field_lens[i] + 1; } @@ -5672,18 +5683,34 @@ void User_var_log_event::pack_info(THD *thd, Protocol* protocol) User_var_log_event:: -User_var_log_event(const char* buf, +User_var_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) :Log_event(buf, description_event) #ifndef MYSQL_CLIENT , deferred(false) #endif { + bool error= false; + const char* buf_start= buf; /* 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; + + /* + We don't know yet is_null value, so we must assume that name_len + may have the bigger value possible, is_null= True and there is no + payload for val. + */ + if (0 == name_len || + !valid_buffer_range<uint>(name_len, buf_start, name, + event_len - UV_VAL_IS_NULL)) + { + error= true; + goto err; + } + buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; if (is_null) @@ -5695,13 +5722,31 @@ User_var_log_event(const char* buf, } else { + if (!valid_buffer_range<uint>(UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE, + buf_start, buf, event_len)) + { + error= true; + goto err; + } + type= (Item_result) buf[UV_VAL_IS_NULL]; charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE); val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE); + + if (!valid_buffer_range<uint>(val_len, buf_start, val, event_len)) + { + error= true; + goto err; + } } + +err: + if (error) + name= 0; } @@ -5843,8 +5888,9 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char *hex_str; CHARSET_INFO *cs; - if (!(hex_str= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits / byte - break; // no error, as we are 'void' + hex_str= (char *)my_malloc(2*val_len+1+2,MYF(MY_WME)); // 2 hex digits / byte + if (!hex_str) + return; str_to_hex(hex_str, val, val_len); /* For proper behaviour when mysqlbinlog|mysql, we need to explicitely @@ -5862,7 +5908,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) my_b_printf(&cache, ":=_%s %s COLLATE %`s%s\n", cs->csname, hex_str, cs->name, print_event_info->delimiter); - my_afree(hex_str); + my_free(hex_str, MYF(MY_WME)); } break; case ROW_RESULT: @@ -7085,9 +7131,9 @@ void Execute_load_query_log_event::pack_info(THD *thd, Protocol *protocol) buf.real_alloc(9 + db_len + q_len + 10 + 21); if (db && db_len) { - if (buf.append("use ") || + if (buf.append(STRING_WITH_LEN("use ")) || append_identifier(thd, &buf, db, db_len) || - buf.append("; ")) + buf.append(STRING_WITH_LEN("; "))) return; } if (query && q_len && buf.append(query, q_len)) diff --git a/sql/log_event.h b/sql/log_event.h index 7a75e90d82f..bab2ab2a43c 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2499,7 +2499,7 @@ public: void print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif - User_var_log_event(const char* buf, + User_var_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} @@ -2511,9 +2511,9 @@ public: and which case the applier adjusts execution path. */ bool is_deferred() { return deferred; } - void set_deferred() { deferred= val; } + void set_deferred() { deferred= true; } #endif - bool is_valid() const { return 1; } + bool is_valid() const { return name != 0; } private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 337825fa857..6a7a4a0476b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -502,6 +502,41 @@ protected: */ #define MAX_TIME_ZONE_NAME_LENGTH (NAME_LEN + 1) +/* + Check how many bytes are available on buffer. + + @param buf_start Pointer to buffer start. + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return Number of bytes available on event buffer. +*/ +template <class T> T available_buffer(const char* buf_start, + const char* buf_current, + T buf_len) +{ + return buf_len - (buf_current - buf_start); +} + +/* + Check if jump value is within buffer limits. + + @param jump Number of positions we want to advance. + @param buf_start Pointer to buffer start + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return True If jump value is within buffer limits. + False Otherwise. +*/ +template <class T> bool valid_buffer_range(T jump, + const char* buf_start, + const char* buf_current, + T buf_len) +{ + return (jump <= available_buffer(buf_start, buf_current, buf_len)); +} + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 01b23c97aee..3a25371e3dc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4941,7 +4941,7 @@ void create_thread_to_handle_connection(THD *thd) if (cached_thread_count > wake_thread) { /* Get thread from cache */ - thread_cache.append(thd); + thread_cache.push_back(thd); wake_thread++; pthread_cond_signal(&COND_thread_cache); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 473baa9ab9b..53f801bd0cf 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3838,8 +3838,6 @@ typedef struct st_sp_table Multi-set key: db_name\0table_name\0alias\0 - for normal tables db_name\0table_name\0 - for temporary tables - Note that in both cases we don't take last '\0' into account when - we count length of key. */ LEX_STRING qname; uint db_length, table_name_length; @@ -3896,19 +3894,26 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) for (; table ; table= table->next_global) if (!table->derived && !table->schema_table) { - char tname[(SAFE_NAME_LEN + 1) * 3]; // db\0table\0alias\0 - uint tlen, alen; - - tlen= table->db_length; - memcpy(tname, table->db, tlen); - tname[tlen++]= '\0'; - memcpy(tname+tlen, table->table_name, table->table_name_length); - tlen+= table->table_name_length; - tname[tlen++]= '\0'; - alen= strlen(table->alias); - memcpy(tname+tlen, table->alias, alen); - tlen+= alen; - tname[tlen]= '\0'; + /* + Structure of key for the multi-set is "db\0table\0alias\0". + Since "alias" part can have arbitrary length we use String + object to construct the key. By default String will use + buffer allocated on stack with NAME_LEN bytes reserved for + alias, since in most cases it is going to be smaller than + NAME_LEN bytes. + */ + char tname_buff[(SAFE_NAME_LEN + 1) * 3]; + String tname(tname_buff, sizeof(tname_buff), &my_charset_bin); + uint temp_table_key_length; + + tname.length(0); + tname.append(table->db, table->db_length); + tname.append('\0'); + tname.append(table->table_name, table->table_name_length); + tname.append('\0'); + temp_table_key_length= tname.length(); + tname.append(table->alias); + tname.append('\0'); /* Upgrade the lock type because this table list will be used @@ -3923,9 +3928,10 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) (and therefore should not be prelocked). Otherwise we will erroneously treat table with same name but with different alias as non-temporary. */ - if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tlen)) || - ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, - tlen - alen - 1)) && + if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname.ptr(), + tname.length())) || + ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname.ptr(), + temp_table_key_length)) && tab->temp)) { if (tab->lock_type < table->lock_type) @@ -3944,11 +3950,11 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE) { tab->temp= TRUE; - tab->qname.length= tlen - alen - 1; + tab->qname.length= temp_table_key_length; } else - tab->qname.length= tlen; - tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1); + tab->qname.length= tname.length(); + tab->qname.str= (char*) thd->memdup(tname.ptr(), tab->qname.length); if (!tab->qname.str) return FALSE; tab->table_name_length= table->table_name_length; @@ -4017,7 +4023,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * stab->lock_count)) || !(key_buff= (char*)thd->memdup(stab->qname.str, - stab->qname.length + 1))) + stab->qname.length))) DBUG_RETURN(FALSE); for (uint j= 0; j < stab->lock_count; j++) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4f4c0eeb06b..021cbb3b7bb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab 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 @@ -196,7 +196,17 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); - +/* + Enumeration of various ACL's and Hashes used in handle_grant_struct() +*/ +enum enum_acl_lists +{ + USER_ACL= 0, + DB_ACL, + COLUMN_PRIVILEGES_HASH, + PROC_PRIVILEGES_HASH, + FUNC_PRIVILEGES_HASH +}; /* Convert scrambled password to binary form, according to scramble type, Binary form is stored in user.salt. @@ -5431,19 +5441,19 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, Delete from grant structure if drop is true. Update in grant structure if drop is false and user_to is not NULL. Search in grant structure if drop is false and user_to is NULL. - Structures are numbered as follows: - 0 acl_users - 1 acl_dbs - 2 column_priv_hash - 3 proc_priv_hash - 4 func_priv_hash + Structures are enumerated as follows: + 0 ACL_USER + 1 ACL_DB + 2 COLUMN_PRIVILEGES_HASH + 3 PROC_PRIVILEGES_HASH + 4 FUNC_PRIVILEGES_HASH @retval > 0 At least one element matched. @retval 0 OK, but no element matched. - @retval -1 Wrong arguments to function. + @retval -1 Wrong arguments to function or Out of Memory */ -static int handle_grant_struct(uint struct_no, bool drop, +static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, LEX_USER *user_from, LEX_USER *user_to) { int result= 0; @@ -5466,21 +5476,21 @@ static int handle_grant_struct(uint struct_no, bool drop, /* Get the number of elements in the in-memory structure. */ switch (struct_no) { - case 0: + case USER_ACL: elements= acl_users.elements; break; - case 1: + case DB_ACL: elements= acl_dbs.elements; break; - case 2: + case COLUMN_PRIVILEGES_HASH: grant_name_hash= &column_priv_hash; elements= grant_name_hash->records; break; - case 3: + case PROC_PRIVILEGES_HASH: grant_name_hash= &proc_priv_hash; elements= grant_name_hash->records; break; - case 4: + case FUNC_PRIVILEGES_HASH: grant_name_hash= &func_priv_hash; elements= grant_name_hash->records; break; @@ -5499,21 +5509,21 @@ static int handle_grant_struct(uint struct_no, bool drop, Get a pointer to the element. */ switch (struct_no) { - case 0: + case USER_ACL: acl_user= dynamic_element(&acl_users, idx, ACL_USER*); user= acl_user->user; host= acl_user->host.hostname; break; - case 1: + case DB_ACL: acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); user= acl_db->user; host= acl_db->host.hostname; break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: grant_name= (GRANT_NAME*) hash_element(grant_name_hash, idx); user= grant_name->user; host= grant_name->host.hostname; @@ -5539,17 +5549,17 @@ static int handle_grant_struct(uint struct_no, bool drop, if ( drop ) { switch ( struct_no ) { - case 0: + case USER_ACL: delete_dynamic_element(&acl_users, idx); break; - case 1: + case DB_ACL: delete_dynamic_element(&acl_dbs, idx); break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: hash_delete(grant_name_hash, (uchar*) grant_name); break; } @@ -5572,19 +5582,19 @@ static int handle_grant_struct(uint struct_no, bool drop, else if ( user_to ) { switch ( struct_no ) { - case 0: + case USER_ACL: acl_user->user= strdup_root(&mem, user_to->user.str); acl_user->host.hostname= strdup_root(&mem, user_to->host.str); break; - case 1: + case DB_ACL: acl_db->user= strdup_root(&mem, user_to->user.str); acl_db->host.hostname= strdup_root(&mem, user_to->host.str); break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: { /* Save old hash key and its length to be able properly update @@ -5605,8 +5615,8 @@ static int handle_grant_struct(uint struct_no, bool drop, is renamed, the hash key is changed. Update the hash to ensure that the position matches the new hash key value */ - hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key, - old_key_length); + my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key, + old_key_length); /* hash_update() operation could have moved element from the tail of the hash to the current position. So we need to take a look @@ -5675,7 +5685,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle user array. */ - if ((handle_grant_struct(0, drop, user_from, user_to)) || found) + if ((handle_grant_struct(USER_ACL, drop, user_from, user_to)) || found) { result= 1; /* At least one record/element found. */ /* If search is requested, we do not need to search further. */ @@ -5693,7 +5703,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle db array. */ - if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(DB_ACL, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -5712,7 +5722,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle procs array. */ - if (((handle_grant_struct(3, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(PROC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -5721,7 +5731,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, goto end; } /* Handle funcs array. */ - if (((handle_grant_struct(4, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(FUNC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -5756,7 +5766,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle columns hash. */ - if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(COLUMN_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) result= 1; /* At least one record/element found. */ } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 01ae9160b24..1971911fb88 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4179,34 +4179,17 @@ retry: char query_buf[2*FN_REFLEN + 21]; String query(query_buf, sizeof(query_buf), system_charset_info); query.length(0); - if (query.ptr()) - { - /* this DELETE FROM is needed even with row-based binlogging */ - query.append("DELETE FROM "); - append_identifier(thd, &query, share->db.str, share->db.length); - query.append("."); - append_identifier(thd, &query, share->table_name.str, - share->table_name.length); - int errcode= query_error_code(thd, TRUE); - if (thd->binlog_query(THD::STMT_QUERY_TYPE, - query.ptr(), query.length(), - FALSE, FALSE, errcode)) - goto err; - } - else - { - /* - As replication is maybe going to be corrupted, we need to warn the - DBA on top of warning the client (which will automatically be done - because of MYF(MY_WME) in my_malloc() above). - */ - sql_print_error("When opening HEAP table, could not allocate memory " - "to write 'DELETE FROM %`s.%`s' to the binary log", - table_list->db, table_list->table_name); - delete entry->triggers; - closefrm(entry, 0); + /* this DELETE FROM is needed even with row-based binlogging */ + query.append("DELETE FROM "); + append_identifier(thd, &query, share->db.str, share->db.length); + query.append("."); + append_identifier(thd, &query, share->table_name.str, + share->table_name.length); + int errcode= query_error_code(thd, TRUE); + if (thd->binlog_query(THD::STMT_QUERY_TYPE, + query.ptr(), query.length(), + FALSE, FALSE, errcode)) goto err; - } } } DBUG_RETURN(0); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 3caaea5bfb7..f8b919b1c38 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -350,6 +350,7 @@ check_user(THD *thd, enum enum_server_command command, USER_RESOURCES ur; int res= acl_getroot(thd, &ur, passwd, passwd_len); + DBUG_EXECUTE_IF("password_format_mismatch",{res= -1;};); #ifndef EMBEDDED_LIBRARY if (res == -1) { @@ -360,6 +361,12 @@ check_user(THD *thd, enum enum_server_command command, in old format. */ NET *net= &thd->net; + DBUG_EXECUTE_IF("password_format_mismatch", + { + inc_host_errors(&thd->remote.sin_addr); + my_error(ER_HANDSHAKE_ERROR, MYF(0)); + DBUG_RETURN(1); + };); if (opt_secure_auth_local) { my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0), @@ -696,6 +703,19 @@ static int check_connection(THD *thd) my_error(ER_BAD_HOST_ERROR, MYF(0)); return 1; } + /* BEGIN : DEBUG */ + DBUG_EXECUTE_IF("addr_fake_ipv4", + { + struct sockaddr *sa= (sockaddr *) &net->vio->remote; + sa->sa_family= AF_INET; + struct in_addr *ip4= &((struct sockaddr_in *)sa)->sin_addr; + /* See RFC 5737, 192.0.2.0/23 is reserved */ + const char* fake= "192.0.2.4"; + ip4->s_addr= inet_addr(fake); + strcpy(ip, fake); + };); + /* END : DEBUG */ + if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) return 1; /* The error is set by my_strdup(). */ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; @@ -796,8 +816,6 @@ static int check_connection(THD *thd) #ifdef _CUSTOMCONFIG_ #include "_cust_sql_parse.h" #endif - if (connect_errors) - reset_host_errors(&thd->remote.sin_addr); if (thd->packet.alloc(thd->variables.net_buffer_length)) return 1; /* The error is set by alloc(). */ @@ -942,11 +960,23 @@ static int check_connection(THD *thd) user[user_len]= '\0'; } - if (thd->main_security_ctx.user) - x_free(thd->main_security_ctx.user); + x_free(thd->main_security_ctx.user); if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME)))) return 1; /* The error is set by my_strdup(). */ - return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE); + + if (!check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE)) + { + /* + Call to reset_host_errors() should be made only when all sanity checks + are done and connection is going to be a successful. + */ + reset_host_errors(&thd->remote.sin_addr); + return 0; + } + else + { + return 1; + } error: inc_host_errors(&thd->remote.sin_addr); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a407faf3c5e..6313a1978ae 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -880,7 +881,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) { long deleted=0; int error= 0; - char path[FN_REFLEN+16]; + char path[FN_REFLEN + 16]; MY_DIR *dirp; uint length; TABLE_LIST* dropped_tables= 0; @@ -1018,7 +1019,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN))) goto exit; /* not much else we can do */ - query_pos= query_data_start= strmov(query,"drop table "); + query_pos= query_data_start= strmov(query,"DROP TABLE "); query_end= query + MAX_DROP_TABLE_Q_LEN; db_len= strlen(db); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b5b69add9b5..48b6a0db81b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3478,9 +3478,8 @@ int select_create::write_to_binlog(bool is_trans, int errcode) if (f != field) query.append(STRING_WITH_LEN(",")); - query.append(STRING_WITH_LEN("`")); - query.append((*f)->field_name, strlen((*f)->field_name)); - query.append(STRING_WITH_LEN("`")); + append_identifier(thd, &query, (*f)->field_name, + strlen((*f)->field_name)); } query.append(STRING_WITH_LEN(") ")); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b95c3981310..6d18ca000c6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. 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 @@ -1626,6 +1627,7 @@ void st_select_lex::init_query() ref_pointer_array= 0; select_n_where_fields= 0; select_n_having_items= 0; + n_child_sum_items= 0; subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; diff --git a/sql/sql_list.h b/sql/sql_list.h index 27882d057b8..975a860b3f5 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -1,7 +1,6 @@ #ifndef INCLUDES_MYSQL_SQL_LIST_H #define INCLUDES_MYSQL_SQL_LIST_H -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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 @@ -165,6 +164,14 @@ protected: public: uint elements; + bool operator==(const base_list &rhs) const + { + return + elements == rhs.elements && + first == rhs.first && + last == rhs.last; + } + inline void empty() { elements=0; first= &end_of_list; last=&first;} inline base_list() { empty(); } /** diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 5bc91eff001..1d43e5898b0 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -40,6 +40,7 @@ #define TIME_I_S_DECIMAL_SIZE (TIME_FLOAT_DIGITS*100)+(TIME_FLOAT_DIGITS-3) #define MAX_QUERY_LENGTH 300 +#define MAX_QUERY_HISTORY 101 /** Connects Information_Schema and Profiling. @@ -253,9 +254,12 @@ void PROF_MEASUREMENT::collect() QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg) :profiling(profiling_arg), profiling_query_id(0), query_source(NULL) { - profile_start= new PROF_MEASUREMENT(this, status_arg); - entries.push_back(profile_start); - profile_end= profile_start; + m_seq_counter= 1; + PROF_MEASUREMENT *prof= new PROF_MEASUREMENT(this, status_arg); + prof->m_seq= m_seq_counter++; + m_start_time_usecs= prof->time_usecs; + m_end_time_usecs= m_start_time_usecs; + entries.push_back(prof); } QUERY_PROFILE::~QUERY_PROFILE() @@ -295,9 +299,14 @@ void QUERY_PROFILE::new_status(const char *status_arg, else prof= new PROF_MEASUREMENT(this, status_arg); - profile_end= prof; + prof->m_seq= m_seq_counter++; + m_end_time_usecs= prof->time_usecs; entries.push_back(prof); + /* Maintain the query history size. */ + while (entries.elements > MAX_QUERY_HISTORY) + delete entries.pop(); + DBUG_VOID_RETURN; } @@ -457,8 +466,7 @@ bool PROFILING::show_profiles() String elapsed; - PROF_MEASUREMENT *ps= prof->profile_start; - PROF_MEASUREMENT *pe= prof->profile_end; + double query_time_usecs= prof->m_end_time_usecs - prof->m_start_time_usecs; if (++idx <= unit->offset_limit_cnt) continue; @@ -467,7 +475,7 @@ bool PROFILING::show_profiles() protocol->prepare_for_resend(); protocol->store((uint32)(prof->profiling_query_id)); - protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000), + protocol->store((double)(query_time_usecs/(1000.0*1000)), (uint32) TIME_FLOAT_DIGITS-1, &elapsed); if (prof->query_source != NULL) protocol->store(prof->query_source, strlen(prof->query_source), @@ -527,17 +535,18 @@ int PROFILING::fill_statistics_info(THD *thd_arg, TABLE_LIST *tables, Item *cond us also include a numbering of each state per query. The query_id and the "seq" together are unique. */ - ulonglong seq; + ulong seq; void *entry_iterator; PROF_MEASUREMENT *entry, *previous= NULL; /* ...and for each query, go through all its state-change steps. */ - for (seq= 0, entry_iterator= query->entries.new_iterator(); + for (entry_iterator= query->entries.new_iterator(); entry_iterator != NULL; entry_iterator= query->entries.iterator_next(entry_iterator), - seq++, previous=entry, row_number++) + previous=entry, row_number++) { entry= query->entries.iterator_value(entry_iterator); + seq= entry->m_seq; /* Skip the first. We count spans of fence, not fence-posts. */ if (previous == NULL) continue; diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 297130962d8..1c30d690c47 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -182,6 +182,7 @@ private: char *file; unsigned int line; + ulong m_seq; double time_usecs; char *allocated_status_memory; @@ -213,8 +214,9 @@ private: query_id_t profiling_query_id; /* Session-specific id. */ char *query_source; - PROF_MEASUREMENT *profile_start; - PROF_MEASUREMENT *profile_end; + double m_start_time_usecs; + double m_end_time_usecs; + ulong m_seq_counter; Queue<PROF_MEASUREMENT> entries; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 19bbef658ab..bc8b7a9e815 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. - 2009-2011 Monty Program Ab +/* Copyright (c) 2000, 2012 Oracle and/or its affiliates. + Copyright (c) 2009, 2013 Monty Program Ab. 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 @@ -1661,6 +1661,8 @@ JOIN::optimize() */ void JOIN::restore_tmp() { + DBUG_PRINT("info", ("restore_tmp this %p tmp_join %p", this, tmp_join)); + DBUG_ASSERT(tmp_join != this); memcpy(tmp_join, this, (size_t) sizeof(JOIN)); } @@ -7158,21 +7160,19 @@ void JOIN::cleanup(bool full) } } } - /* - We are not using tables anymore - Unlock all tables. We may be in an INSERT .... SELECT statement. - */ if (full) { - if (tmp_join) - tmp_table_param.copy_field= 0; - group_fields.delete_elements(); /* - Ensure that the above delete_elements() would not be called + Ensure that the following delete_elements() would not be called twice for the same list. */ - if (tmp_join && tmp_join != this) - tmp_join->group_fields= group_fields; + if (tmp_join && tmp_join != this && + tmp_join->group_fields == this->group_fields) + tmp_join->group_fields.empty(); + + // Run Cached_item DTORs! + group_fields.delete_elements(); + /* We can't call delete_elements() on copy_funcs as this will cause problems in free_elements() as some of the elements are then deleted. |