diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:13:32 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:13:32 +0100 |
commit | d3935adf7a4ea943583e9e51fe8fa8a2c14521dd (patch) | |
tree | 4125365a32fa25dde9e79ccfb4dcd10269071607 /sql | |
parent | 85ea99dcaf8fd91fa566a78062dbfa416c2309fe (diff) | |
parent | 14ba37f76f87cc48cae62eb6bdf3cda294dff78d (diff) | |
download | mariadb-git-d3935adf7a4ea943583e9e51fe8fa8a2c14521dd.tar.gz |
mysql-5.5.29 merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/CMakeLists.txt | 1 | ||||
-rw-r--r-- | sql/event_db_repository.cc | 10 | ||||
-rw-r--r-- | sql/filesort.cc | 5 | ||||
-rw-r--r-- | sql/ha_partition.cc | 216 | ||||
-rw-r--r-- | sql/ha_partition.h | 4 | ||||
-rw-r--r-- | sql/handler.cc | 41 | ||||
-rw-r--r-- | sql/handler.h | 4 | ||||
-rw-r--r-- | sql/hostname.cc | 56 | ||||
-rw-r--r-- | sql/item_subselect.cc | 31 | ||||
-rw-r--r-- | sql/log_event_old.cc | 7 | ||||
-rw-r--r-- | sql/opt_range.cc | 60 | ||||
-rw-r--r-- | sql/records.cc | 10 | ||||
-rw-r--r-- | sql/sp.cc | 16 | ||||
-rw-r--r-- | sql/sp_head.cc | 4 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 11 | ||||
-rw-r--r-- | sql/sp_rcontext.h | 45 | ||||
-rw-r--r-- | sql/sql_acl.cc | 80 | ||||
-rw-r--r-- | sql/sql_handler.cc | 29 | ||||
-rw-r--r-- | sql/sql_help.cc | 10 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 | ||||
-rw-r--r-- | sql/sql_select.cc | 41 | ||||
-rw-r--r-- | sql/sql_show.cc | 12 | ||||
-rw-r--r-- | sql/sql_signal.cc | 12 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 11 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 | ||||
-rw-r--r-- | sql/tztime.cc | 32 | ||||
-rw-r--r-- | sql/uniques.cc | 7 |
28 files changed, 594 insertions, 180 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index ecf91fcf043..a5f1fcb60ec 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -295,7 +295,6 @@ IF(WIN32 AND MYSQLD_EXECUTABLE) COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -P ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data - COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep DEPENDS mysqld ) ADD_CUSTOM_TARGET(initial_database diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 0eb65cff91e..14927a66915 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -409,7 +409,6 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table, const char *db) { - int ret=0; CHARSET_INFO *scs= system_charset_info; KEY *key_info; uint key_len; @@ -419,7 +418,14 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, DBUG_ENTER("Event_db_repository::index_read_for_db_for_i_s"); DBUG_PRINT("info", ("Using prefix scanning on PK")); - event_table->file->ha_index_init(0, 1); + + int ret= event_table->file->ha_index_init(0, 1); + if (ret) + { + event_table->file->print_error(ret, MYF(0)); + DBUG_RETURN(true); + } + key_info= event_table->key_info; if (key_info->key_parts == 0 || diff --git a/sql/filesort.cc b/sql/filesort.cc index 79ccf835c5f..e68fc1dc594 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -136,6 +136,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, */ memcpy(&table_sort, &table->sort, sizeof(FILESORT_INFO)); table->sort.io_cache= NULL; + DBUG_ASSERT(table_sort.record_pointers == NULL); outfile= table_sort.io_cache; my_b_clear(&tempfile); @@ -364,6 +365,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, void filesort_free_buffers(TABLE *table, bool full) { + DBUG_ENTER("filesort_free_buffers"); my_free(table->sort.record_pointers); table->sort.record_pointers= NULL; @@ -380,6 +382,7 @@ void filesort_free_buffers(TABLE *table, bool full) my_free(table->sort.addon_field); table->sort.addon_buf= NULL; table->sort.addon_field= NULL; + DBUG_VOID_RETURN; } @@ -529,6 +532,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, if (!quick_select) { next_pos=(uchar*) 0; /* Find records in sequence */ + DBUG_EXECUTE_IF("bug14365043_1", + DBUG_SET("+d,ha_rnd_init_fail");); if (file->ha_rnd_init_with_error(1)) DBUG_RETURN(HA_POS_ERROR); file->extra_opt(HA_EXTRA_CACHE, diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 9cbb8e16f8a..4cf66daf315 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2857,6 +2857,17 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) if (bitmap_init(&m_bulk_insert_started, NULL, m_tot_parts + 1, FALSE)) DBUG_RETURN(error); bitmap_clear_all(&m_bulk_insert_started); + /* + Initialize the bitmap we use to keep track of partitions which returned + HA_ERR_KEY_NOT_FOUND from index_read_map. + */ + if (bitmap_init(&m_key_not_found_partitions, NULL, m_tot_parts, FALSE)) + { + bitmap_free(&m_bulk_insert_started); + DBUG_RETURN(error); + } + bitmap_clear_all(&m_key_not_found_partitions); + m_key_not_found= false; /* Initialize the bitmap we use to determine what partitions are used */ if (!m_is_clone_of) { @@ -2999,6 +3010,7 @@ err_handler: (*file)->ha_close(); err_alloc: bitmap_free(&m_bulk_insert_started); + bitmap_free(&m_key_not_found_partitions); if (!m_is_clone_of) bitmap_free(&(m_part_info->used_partitions)); @@ -3075,6 +3087,7 @@ int ha_partition::close(void) DBUG_ASSERT(table->s == table_share); destroy_record_priority_queue(); bitmap_free(&m_bulk_insert_started); + bitmap_free(&m_key_not_found_partitions); if (!m_is_clone_of) bitmap_free(&(m_part_info->used_partitions)); file= m_file; @@ -4614,21 +4627,24 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key, } -/* +/** Common routine for a number of index_read variants - SYNOPSIS - ha_partition::common_index_read() - buf Buffer where the record should be returned - have_start_key TRUE <=> the left endpoint is available, i.e. - we're in index_read call or in read_range_first - call and the range has left endpoint - - FALSE <=> there is no left endpoint (we're in - read_range_first() call and the range has no left - endpoint) + @param buf Buffer where the record should be returned. + @param have_start_key TRUE <=> the left endpoint is available, i.e. + we're in index_read call or in read_range_first + call and the range has left endpoint. + FALSE <=> there is no left endpoint (we're in + read_range_first() call and the range has no left + endpoint). - DESCRIPTION + @return Operation status + @retval 0 OK + @retval HA_ERR_END_OF_FILE Whole index scanned, without finding the record. + @retval HA_ERR_KEY_NOT_FOUND Record not found, but index cursor positioned. + @retval other error code. + + @details Start scanning the range (when invoked from read_range_first()) or doing an index lookup (when invoked from index_read_XXX): - If possible, perform partition selection @@ -4638,10 +4654,6 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key, handle_unordered_scan_next_partition) YES: Fill the priority queue and get the record that is the first in the ordering - - RETURN - 0 OK - other HA_ERR_END_OF_FILE or other error code. */ int ha_partition::common_index_read(uchar *buf, bool have_start_key) @@ -4651,14 +4663,16 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key) bool reverse_order= FALSE; DBUG_ENTER("ha_partition::common_index_read"); - DBUG_PRINT("info", ("m_ordered: %u have_start_key: %u", - m_ordered, have_start_key)); + DBUG_PRINT("info", ("m_ordered %u m_ordered_scan_ong %u", + m_ordered, m_ordered_scan_ongoing)); if (have_start_key) { m_start_key.length= key_len= calculate_key_len(table, active_index, m_start_key.key, m_start_key.keypart_map); + DBUG_PRINT("info", ("have_start_key map %lu find_flag %u len %u", + m_start_key.keypart_map, m_start_key.flag, key_len)); DBUG_ASSERT(key_len); } if ((error= partition_scan_set_up(buf, have_start_key))) @@ -4676,24 +4690,16 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key) } DBUG_PRINT("info", ("m_ordered %u m_o_scan_ong %u have_start_key %u", m_ordered, m_ordered_scan_ongoing, have_start_key)); - if (!m_ordered_scan_ongoing || - (have_start_key && m_start_key.flag == HA_READ_KEY_EXACT && - !m_pkey_is_clustered && - key_len >= m_curr_key_info[0]->key_length)) + if (!m_ordered_scan_ongoing) { /* - We use unordered index scan either when read_range is used and flag - is set to not use ordered or when an exact key is used and in this - case all records will be sorted equal and thus the sort order of the - resulting records doesn't matter. + We use unordered index scan when read_range is used and flag + is set to not use ordered. We also use an unordered index scan when the number of partitions to scan is only one. The unordered index scan will use the partition set created. - Need to set unordered scan ongoing since we can come here even when - it isn't set. */ DBUG_PRINT("info", ("doing unordered scan")); - m_ordered_scan_ongoing= FALSE; error= handle_unordered_scan_next_partition(buf); } else @@ -4874,6 +4880,8 @@ int ha_partition::index_next(uchar * buf) TODO(low priority): If we want partition to work with the HANDLER commands, we must be able to do index_last() -> index_prev() -> index_next() + and if direction changes, we must step back those partitions in + the record queue so we don't return a value from the wrong direction. */ DBUG_ASSERT(m_index_scan_type != partition_index_last); if (!m_ordered_scan_ongoing) @@ -5127,10 +5135,18 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) int ha_partition::handle_unordered_next(uchar *buf, bool is_next_same) { - handler *file= m_file[m_part_spec.start_part]; + handler *file; int error; DBUG_ENTER("ha_partition::handle_unordered_next"); + if (m_part_spec.start_part >= m_tot_parts) + { + /* Should never happen! */ + DBUG_ASSERT(0); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + file= m_file[m_part_spec.start_part]; + /* We should consider if this should be split into three functions as partition_read_range is_next_same are always local constants @@ -5191,6 +5207,7 @@ int ha_partition::handle_unordered_next(uchar *buf, bool is_next_same) int ha_partition::handle_unordered_scan_next_partition(uchar * buf) { uint i; + int saved_error= HA_ERR_END_OF_FILE; DBUG_ENTER("ha_partition::handle_unordered_scan_next_partition"); for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++) @@ -5241,26 +5258,33 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf) } if ((error != HA_ERR_END_OF_FILE) && (error != HA_ERR_KEY_NOT_FOUND)) DBUG_RETURN(error); - DBUG_PRINT("info", ("HA_ERR_END_OF_FILE on partition %d", i)); + + /* + If HA_ERR_KEY_NOT_FOUND, we must return that error instead of + HA_ERR_END_OF_FILE, to be able to continue search. + */ + if (saved_error != HA_ERR_KEY_NOT_FOUND) + saved_error= error; + DBUG_PRINT("info", ("END_OF_FILE/KEY_NOT_FOUND on partition %d", i)); } - m_part_spec.start_part= NO_CURRENT_PART_ID; - DBUG_RETURN(HA_ERR_END_OF_FILE); + if (saved_error == HA_ERR_END_OF_FILE) + m_part_spec.start_part= NO_CURRENT_PART_ID; + DBUG_RETURN(saved_error); } -/* - Common routine to start index scan with ordered results +/** + Common routine to start index scan with ordered results. - SYNOPSIS - handle_ordered_index_scan() - out:buf Read row in MySQL Row Format + @param[out] buf Read row in MySQL Row Format - RETURN VALUE - HA_ERR_END_OF_FILE End of scan - 0 Success - other Error code + @return Operation status + @retval HA_ERR_END_OF_FILE End of scan + @retval HA_ERR_KEY_NOT_FOUNE End of scan + @retval 0 Success + @retval other Error code - DESCRIPTION + @details This part contains the logic to handle index scans that require ordered output. This includes all except those started by read_range_first with the flag ordered set to FALSE. Thus most direct index_read and all @@ -5282,8 +5306,14 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) uint j= queue_first_element(&m_queue); bool found= FALSE; uchar *part_rec_buf_ptr= m_ordered_rec_buffer; + int saved_error= HA_ERR_END_OF_FILE; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); + if (m_key_not_found) + { + m_key_not_found= false; + bitmap_clear_all(&m_key_not_found_partitions); + } m_top_entry= NO_CURRENT_PART_ID; queue_remove_all(&m_queue); @@ -5345,6 +5375,13 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) { DBUG_RETURN(error); } + else if (error == HA_ERR_KEY_NOT_FOUND) + { + DBUG_PRINT("info", ("HA_ERR_KEY_NOT_FOUND from partition %u", i)); + bitmap_set_bit(&m_key_not_found_partitions, i); + m_key_not_found= true; + saved_error= error; + } part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS; } if (found) @@ -5362,7 +5399,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry)); DBUG_RETURN(0); } - DBUG_RETURN(HA_ERR_END_OF_FILE); + DBUG_RETURN(saved_error); } @@ -5390,6 +5427,59 @@ void ha_partition::return_top_record(uchar *buf) } +/** + Add index_next/prev from partitions without exact match. + + If there where any partitions that returned HA_ERR_KEY_NOT_FOUND when + ha_index_read_map was done, those partitions must be included in the + following index_next/prev call. +*/ + +int ha_partition::handle_ordered_index_scan_key_not_found() +{ + int error; + uint i; + uchar *part_buf= m_ordered_rec_buffer; + uchar *curr_rec_buf= NULL; + DBUG_ENTER("ha_partition::handle_ordered_index_scan_key_not_found"); + DBUG_ASSERT(m_key_not_found); + /* + Loop over all used partitions to get the correct offset + into m_ordered_rec_buffer. + */ + for (i= 0; i < m_tot_parts; i++) + { + if (!bitmap_is_set(&m_part_info->used_partitions, i)) + continue; + + if (bitmap_is_set(&m_key_not_found_partitions, i)) + { + /* + This partition is used and did return HA_ERR_KEY_NOT_FOUND + in index_read_map. + */ + curr_rec_buf= part_buf + PARTITION_BYTES_IN_POS; + error= m_file[i]->index_next(curr_rec_buf); + /* HA_ERR_KEY_NOT_FOUND is not allowed from index_next! */ + DBUG_ASSERT(error != HA_ERR_KEY_NOT_FOUND); + if (!error) + queue_insert(&m_queue, part_buf); + else if (error != HA_ERR_END_OF_FILE && error != HA_ERR_KEY_NOT_FOUND) + DBUG_RETURN(error); + } + part_buf+= m_rec_length + PARTITION_BYTES_IN_POS; + } + DBUG_ASSERT(curr_rec_buf); + bitmap_clear_all(&m_key_not_found_partitions); + m_key_not_found= false; + + /* Update m_top_entry, which may have changed. */ + uchar *key_buffer= queue_top(&m_queue); + m_top_entry= uint2korr(key_buffer); + DBUG_RETURN(0); +} + + /* Common routine to handle index_next with ordered results @@ -5409,9 +5499,45 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same) int error; uint part_id= m_top_entry; uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS; - handler *file= m_file[part_id]; + handler *file; DBUG_ENTER("ha_partition::handle_ordered_next"); + if (m_key_not_found) + { + if (is_next_same) + { + /* Only rows which match the key. */ + m_key_not_found= false; + bitmap_clear_all(&m_key_not_found_partitions); + } + else + { + /* There are partitions not included in the index record queue. */ + uint old_elements= m_queue.elements; + if ((error= handle_ordered_index_scan_key_not_found())) + DBUG_RETURN(error); + /* + If the queue top changed, i.e. one of the partitions that gave + HA_ERR_KEY_NOT_FOUND in index_read_map found the next record, + return it. + Otherwise replace the old with a call to index_next (fall through). + */ + if (old_elements != m_queue.elements && part_id != m_top_entry) + { + return_top_record(buf); + DBUG_RETURN(0); + } + } + } + if (part_id >= m_tot_parts) + { + /* This should never happen! */ + DBUG_ASSERT(0); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + + file= m_file[part_id]; + if (m_index_scan_type == partition_read_range) { error= file->read_range_next(); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 86d43e3750f..30262b25bd9 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -182,6 +182,9 @@ private: static int compare_number_of_records(ha_partition *me, const uint32 *a, const uint32 *b); + /** partitions that returned HA_ERR_KEY_NOT_FOUND. */ + MY_BITMAP m_key_not_found_partitions; + bool m_key_not_found; public: handler *clone(const char *name, MEM_ROOT *mem_root); virtual void set_part_info(partition_info *part_info) @@ -516,6 +519,7 @@ private: int handle_unordered_next(uchar * buf, bool next_same); int handle_unordered_scan_next_partition(uchar * buf); int handle_ordered_index_scan(uchar * buf, bool reverse_order); + int handle_ordered_index_scan_key_not_found(); int handle_ordered_next(uchar * buf, bool next_same); int handle_ordered_prev(uchar * buf); void return_top_record(uchar * buf); diff --git a/sql/handler.cc b/sql/handler.cc index 679ef346fbb..11265abb9d0 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2334,18 +2334,25 @@ int handler::read_first_row(uchar * buf, uint primary_key) if (stats.deleted < 10 || primary_key >= MAX_KEY || !(index_flags(primary_key, 0, 0) & HA_READ_ORDER)) { - if ((!(error= ha_rnd_init(1)))) + if (!(error= ha_rnd_init(1))) { - while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED) ; - (void) ha_rnd_end(); + while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED) + /* skip deleted row */; + const int end_error= ha_rnd_end(); + if (!error) + error= end_error; } } else { /* Find the first row through the primary key */ - if (!(error = ha_index_init(primary_key, 0))) + if (!(error= ha_index_init(primary_key, 0))) + { error= ha_index_first(buf); - (void) ha_index_end(); + const int end_error= ha_index_end(); + if (!error) + error= end_error; + } } DBUG_RETURN(error); } @@ -2744,7 +2751,15 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment, table->mark_columns_used_by_index_no_reset(table->s->next_number_index, table->read_set); column_bitmaps_signal(); - ha_index_init(table->s->next_number_index, 1); + + if (ha_index_init(table->s->next_number_index, 1)) + { + /* This should never happen, assert in debug, and fail in release build */ + DBUG_ASSERT(0); + *first_value= ULONGLONG_MAX; + return; + } + if (table->s->next_number_keypart == 0) { // Autoincrement at key-start error=ha_index_last(table->record[1]); @@ -2775,13 +2790,25 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment, } if (error) - nr=1; + { + if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) + { + /* No entry found, start with 1. */ + nr= 1; + } + else + { + DBUG_ASSERT(0); + nr= ULONGLONG_MAX; + } + } else nr= ((ulonglong) table->next_number_field-> val_int_offset(table->s->rec_buff_length)+1); ha_index_end(); (void) extra(HA_EXTRA_NO_KEYREAD); *first_value= nr; + return; } diff --git a/sql/handler.h b/sql/handler.h index af5d7e6d606..9e390b2a62a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1843,6 +1843,7 @@ public: int ha_open(TABLE *table, const char *name, int mode, uint test_if_locked); int ha_index_init(uint idx, bool sorted) { + DBUG_EXECUTE_IF("ha_index_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); int result; DBUG_ENTER("ha_index_init"); DBUG_ASSERT(inited==NONE); @@ -1867,6 +1868,7 @@ public: virtual int prepare_index_scan() { return 0; } int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result)) { + DBUG_EXECUTE_IF("ha_rnd_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); int result; DBUG_ENTER("ha_rnd_init"); DBUG_ASSERT(inited==NONE || (inited==RND && scan)); @@ -2748,7 +2750,7 @@ private: */ virtual int open(const char *name, int mode, uint test_if_locked)=0; - /* Note: ha_index_read_idx_map() may buypass index_init() */ + /* Note: ha_index_read_idx_map() may bypass index_init() */ virtual int index_init(uint idx, bool sorted) { return 0; } virtual int index_end() { return 0; } /** diff --git a/sql/hostname.cc b/sql/hostname.cc index 763c4647532..ee30d071602 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -367,6 +367,14 @@ bool ip_to_hostname(struct sockaddr_storage *ip_storage, err_code= vio_getnameinfo(ip, hostname_buffer, NI_MAXHOST, NULL, 0, NI_NAMEREQD); + /* BEGIN : DEBUG */ + DBUG_EXECUTE_IF("addr_fake_ipv4", + { + strcpy(hostname_buffer, "santa.claus.ipv4.example.com"); + err_code= 0; + };); + /* END : DEBUG */ + if (err_code) { // NOTE: gai_strerror() returns a string ending by a dot. @@ -439,6 +447,12 @@ bool ip_to_hostname(struct sockaddr_storage *ip_storage, DBUG_RETURN(err_status); } + /* + To avoid crashing the server in DBUG_EXECUTE_IF, + Define a variable which depicts state of addr_info_list. + */ + bool free_addr_info_list= false; + /* Get IP-addresses for the resolved host name (FCrDNS technique). */ struct addrinfo hints; @@ -453,6 +467,42 @@ bool ip_to_hostname(struct sockaddr_storage *ip_storage, (const char *) hostname_buffer)); err_code= getaddrinfo(hostname_buffer, NULL, &hints, &addr_info_list); + if (err_code == 0) + free_addr_info_list= true; + + /* BEGIN : DEBUG */ + DBUG_EXECUTE_IF("addr_fake_ipv4", + { + if (free_addr_info_list) + freeaddrinfo(addr_info_list); + + struct sockaddr_in *debug_addr; + static struct sockaddr_in debug_sock_addr[2]; + static struct addrinfo debug_addr_info[2]; + /* Simulating ipv4 192.0.2.5 */ + debug_addr= & debug_sock_addr[0]; + debug_addr->sin_family= AF_INET; + debug_addr->sin_addr.s_addr= inet_addr("192.0.2.5"); + + /* Simulating ipv4 192.0.2.4 */ + debug_addr= & debug_sock_addr[1]; + debug_addr->sin_family= AF_INET; + debug_addr->sin_addr.s_addr= inet_addr("192.0.2.4"); + + debug_addr_info[0].ai_addr= (struct sockaddr*) & debug_sock_addr[0]; + debug_addr_info[0].ai_addrlen= sizeof (struct sockaddr_in); + debug_addr_info[0].ai_next= & debug_addr_info[1]; + + debug_addr_info[1].ai_addr= (struct sockaddr*) & debug_sock_addr[1]; + debug_addr_info[1].ai_addrlen= sizeof (struct sockaddr_in); + debug_addr_info[1].ai_next= NULL; + + addr_info_list= & debug_addr_info[0]; + err_code= 0; + free_addr_info_list= false; + };); + + /* END : DEBUG */ if (err_code == EAI_NONAME) { @@ -505,7 +555,8 @@ bool ip_to_hostname(struct sockaddr_storage *ip_storage, { DBUG_PRINT("error", ("Out of memory.")); - freeaddrinfo(addr_info_list); + if (free_addr_info_list) + freeaddrinfo(addr_info_list); DBUG_RETURN(TRUE); } @@ -539,7 +590,8 @@ bool ip_to_hostname(struct sockaddr_storage *ip_storage, /* Free the result of getaddrinfo(). */ - freeaddrinfo(addr_info_list); + if (free_addr_info_list) + freeaddrinfo(addr_info_list); /* Add an entry for the IP to the cache. */ diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 265db0055ad..dbc4f9818d5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3258,11 +3258,14 @@ int subselect_uniquesubquery_engine::scan_table() TABLE *table= tab->table; DBUG_ENTER("subselect_uniquesubquery_engine::scan_table"); - if (table->file->inited) - table->file->ha_index_end(); - - if (table->file->ha_rnd_init_with_error(1)) - DBUG_RETURN(1); + if ((table->file->inited && + (error= table->file->ha_index_end())) || + (error= table->file->ha_rnd_init(1))) + { + (void) report_error(table, error); + DBUG_RETURN(true); + } + table->file->extra_opt(HA_EXTRA_CACHE, current_thd->variables.read_buff_size); table->null_row= 0; @@ -3398,8 +3401,13 @@ int subselect_uniquesubquery_engine::exec() DBUG_RETURN(0); } - if (!table->file->inited) - table->file->ha_index_init(tab->ref.key, 0); + if (!table->file->inited && + (error= table->file->ha_index_init(tab->ref.key, 0))) + { + (void) report_error(table, error); + DBUG_RETURN(true); + } + error= table->file->ha_index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab-> @@ -3563,8 +3571,13 @@ int subselect_indexsubquery_engine::exec() DBUG_RETURN(0); } - if (!table->file->inited) - table->file->ha_index_init(tab->ref.key, 1); + if (!table->file->inited && + (error= table->file->ha_index_init(tab->ref.key, 1))) + { + (void) report_error(table, error); + DBUG_RETURN(true); + } + error= table->file->ha_index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab-> diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index d7c66af769a..244999fc431 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -725,7 +725,10 @@ static int find_and_fetch_row(TABLE *table, uchar *key) int error; /* We have a key: search the table using the index */ if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE))) + { + table->file->print_error(error, MYF(0)); DBUG_RETURN(error); + } /* Don't print debug messages when running valgrind since they can @@ -858,7 +861,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key) default: table->file->print_error(error, MYF(0)); DBUG_PRINT("info", ("Record not found")); - table->file->ha_rnd_end(); + (void) table->file->ha_rnd_end(); DBUG_RETURN(error); } } @@ -2428,7 +2431,7 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) continue; DBUG_PRINT("info",("no record matching the given row found")); table->file->print_error(error, MYF(0)); - table->file->ha_index_end(); + (void) table->file->ha_index_end(); DBUG_RETURN(error); } } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index b98edeb15db..f3dd3b8e2d0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -117,6 +117,7 @@ #include "records.h" // init_read_record, end_read_record #include <m_ctype.h> #include "sql_select.h" +#include "filesort.h" // filesort_free_buffers #ifndef EXTRA_DEBUG #define test_rb_tree(A,B) {} @@ -1892,7 +1893,8 @@ int QUICK_INDEX_SORT_SELECT::init() int QUICK_INDEX_SORT_SELECT::reset() { DBUG_ENTER("QUICK_INDEX_SORT_SELECT::reset"); - DBUG_RETURN(read_keys_and_merge()); + const int retval= read_keys_and_merge(); + DBUG_RETURN(retval); } bool @@ -2138,8 +2140,9 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) There is no use of this->file. Use it for the first of merged range selects. */ - if (quick->init_ror_merged_scan(TRUE)) - DBUG_RETURN(1); + int error= quick->init_ror_merged_scan(TRUE); + if (error) + DBUG_RETURN(error); quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); } while ((cur= quick_it++)) @@ -2322,8 +2325,8 @@ int QUICK_ROR_UNION_SELECT::reset() List_iterator_fast<QUICK_SELECT_I> it(quick_selects); while ((quick= it++)) { - if (quick->reset()) - DBUG_RETURN(1); + if ((error= quick->reset())) + DBUG_RETURN(error); if ((error= quick->get_next())) { if (error == HA_ERR_END_OF_FILE) @@ -2334,10 +2337,10 @@ int QUICK_ROR_UNION_SELECT::reset() queue_insert(&queue, (uchar*)quick); } - if (head->file->ha_rnd_init_with_error(1)) + if ((error= head->file->ha_rnd_init(1))) { DBUG_PRINT("error", ("ROR index_merge rnd_init call failed")); - DBUG_RETURN(1); + DBUG_RETURN(error); } DBUG_RETURN(0); @@ -10604,7 +10607,10 @@ int read_keys_and_merge_scans(THD *thd, *unique_ptr= unique; } else + { unique->reset(); + filesort_free_buffers(head, false); + } DBUG_ASSERT(file->ref_length == unique->get_size()); DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size()); @@ -10763,6 +10769,13 @@ int QUICK_INDEX_INTERSECT_SELECT::get_next() If a Clustered PK scan is present, it is used only to check if row satisfies its condition (and never used for row retrieval). + Locking: to ensure that exclusive locks are only set on records that + are included in the final result we must release the lock + on all rows we read but do not include in the final result. This + must be done on each index that reads the record and the lock + must be released using the same handler (the same quick object) as + used when reading the record. + RETURN 0 - Ok other - Error code if any error occurred. @@ -10773,6 +10786,12 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects); QUICK_SELECT_WITH_RECORD *qr; QUICK_RANGE_SELECT* quick; + + /* quick that reads the given rowid first. This is needed in order + to be able to unlock the row using the same handler object that locked + it */ + QUICK_RANGE_SELECT* quick_with_last_rowid; + int error, cmp; uint last_rowid_count=0; DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next"); @@ -10786,7 +10805,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() if (cpk_quick) { while (!error && !cpk_quick->row_in_ranges()) + { + quick->file->unlock_row(); /* row not in range; unlock */ error= quick->get_next(); + } } if (error) DBUG_RETURN(error); @@ -10798,6 +10820,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() quick->file->position(quick->record); memcpy(last_rowid, quick->file->ref, head->file->ref_length); last_rowid_count= 1; + quick_with_last_rowid= quick; while (last_rowid_count < quick_selects.elements) { @@ -10811,9 +10834,17 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() do { if ((error= quick->get_next())) + { + quick_with_last_rowid->file->unlock_row(); DBUG_RETURN(error); + } quick->file->position(quick->record); cmp= head->file->cmp_ref(quick->file->ref, last_rowid); + if (cmp < 0) + { + /* This row is being skipped. Release lock on it. */ + quick->file->unlock_row(); + } } while (cmp < 0); key_copy(qr->key_tuple, record, head->key_info + quick->index, @@ -10827,13 +10858,19 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() { while (!cpk_quick->row_in_ranges()) { + quick->file->unlock_row(); /* row not in range; unlock */ if ((error= quick->get_next())) + { + quick_with_last_rowid->file->unlock_row(); DBUG_RETURN(error); + } } quick->file->position(quick->record); } memcpy(last_rowid, quick->file->ref, head->file->ref_length); + quick_with_last_rowid->file->unlock_row(); last_rowid_count= 1; + quick_with_last_rowid= quick; //save the fields here key_copy(qr->key_tuple, record, head->key_info + quick->index, @@ -10956,8 +10993,14 @@ int QUICK_RANGE_SELECT::reset() { if (in_ror_merged_scan) head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); + + DBUG_EXECUTE_IF("bug14365043_2", + DBUG_SET("+d,ha_index_init_fail");); if ((error= file->ha_index_init(index,1))) + { + file->print_error(error, MYF(0)); DBUG_RETURN(error); + } } /* Allocate buffer if we need one but haven't allocated it yet */ @@ -13161,7 +13204,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void) head->enable_keyread(); /* We need only the key attributes */ } if ((result= file->ha_index_init(index,1))) + { + head->file->print_error(result, MYF(0)); DBUG_RETURN(result); + } if (quick_prefix_select && quick_prefix_select->reset()) DBUG_RETURN(1); result= file->ha_index_last(record); diff --git a/sql/records.cc b/sql/records.cc index d52481c36f5..7b2cea2830b 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -68,6 +68,7 @@ static int rr_index_desc(READ_RECORD *info); void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse) { + int error; empty_record(table); bzero((char*) info,sizeof(*info)); info->thd= thd; @@ -77,8 +78,13 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, info->unlock_row= rr_unlock_row; table->status=0; /* And it's always found */ - if (!table->file->inited) - table->file->ha_index_init(idx, 1); + if (!table->file->inited && + (error= table->file->ha_index_init(idx, 1))) + { + if (print_error) + table->file->print_error(error, MYF(0)); + } + /* read_record will be changed to rr_index in rr_index_first */ info->read_record= reverse ? rr_index_last : rr_index_first; } diff --git a/sql/sp.cc b/sql/sp.cc index 93cd64b4104..726d70ffe2a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1452,7 +1452,6 @@ bool lock_db_routines(THD *thd, char *db) { TABLE *table; uint key_len; - int nxtres= 0; Open_tables_backup open_tables_state_backup; MDL_request_list mdl_requests; Lock_db_routines_error_handler err_handler; @@ -1480,7 +1479,13 @@ bool lock_db_routines(THD *thd, char *db) table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info); key_len= table->key_info->key_part[0].store_length; table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW); - table->file->ha_index_init(0, 1); + int nxtres= table->file->ha_index_init(0, 1); + if (nxtres) + { + table->file->print_error(nxtres, MYF(0)); + close_system_tables(thd, &open_tables_state_backup); + DBUG_RETURN(true); + } if (! table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1, HA_READ_KEY_EXACT)) @@ -1543,7 +1548,11 @@ sp_drop_db_routines(THD *thd, char *db) table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW); ret= SP_OK; - table->file->ha_index_init(0, 1); + if (table->file->ha_index_init(0, 1)) + { + ret= SP_KEY_NOT_FOUND; + goto err_idx_init; + } if (!table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1, HA_READ_KEY_EXACT)) { @@ -1569,6 +1578,7 @@ sp_drop_db_routines(THD *thd, char *db) } table->file->ha_index_end(); +err_idx_init: close_thread_tables(thd); /* Make sure to only release the MDL lock on mysql.proc, not other diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 22bce1dad4f..be6dc935dcc 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -4110,9 +4110,9 @@ 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 *)my_hash_search(&m_sptabs, (uchar *)tname.ptr(), + if ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname.ptr(), tname.length())) || - ((tab= (SP_TABLE *)my_hash_search(&m_sptabs, (uchar *)tname.ptr(), + ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname.ptr(), temp_table_key_length)) && tab->temp)) { diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index d78f2a162f5..30acfebabb2 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -67,19 +67,15 @@ sp_rcontext::~sp_rcontext() bool sp_rcontext::init(THD *thd) { uint handler_count= m_root_parsing_ctx->max_handler_index(); - uint i; in_sub_stmt= thd->in_sub_stmt; if (init_var_table(thd) || init_var_items()) return TRUE; - if (!(m_raised_conditions= new (thd->mem_root) MYSQL_ERROR[handler_count])) + if (!(m_raised_conditions= new (thd->mem_root) Sql_condition_info[handler_count])) return TRUE; - for (i= 0; i<handler_count; i++) - m_raised_conditions[i].init(thd->mem_root); - return !(m_handler= (sp_handler_t*)thd->alloc(handler_count * sizeof(sp_handler_t))) || @@ -446,13 +442,12 @@ sp_rcontext::exit_handler() DBUG_VOID_RETURN; } -MYSQL_ERROR* -sp_rcontext::raised_condition() const +Sql_condition_info* sp_rcontext::raised_condition() const { if (m_ihsp > 0) { uint hindex= m_in_handler[m_ihsp - 1].index; - MYSQL_ERROR *raised= & m_raised_conditions[hindex]; + Sql_condition_info *raised= & m_raised_conditions[hindex]; return raised; } diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 3d976f94381..5008a73d96c 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -58,6 +58,46 @@ typedef struct uint index; } sp_active_handler_t; + +class Sql_condition_info : public Sql_alloc +{ +public: + /** SQL error code. */ + uint m_sql_errno; + + /** Error level. */ + MYSQL_ERROR::enum_warning_level m_level; + + /** SQLSTATE. */ + char m_sql_state[SQLSTATE_LENGTH + 1]; + + /** Text message. */ + char m_message[MYSQL_ERRMSG_SIZE]; + + void set(uint sql_errno, const char* sqlstate, + MYSQL_ERROR::enum_warning_level level, + const char* msg) + { + m_sql_errno= sql_errno; + m_level= level; + + memcpy(m_sql_state, sqlstate, SQLSTATE_LENGTH); + m_sql_state[SQLSTATE_LENGTH]= '\0'; + + strncpy(m_message, msg, MYSQL_ERRMSG_SIZE); + } + + void clear() + { + m_sql_errno= 0; + m_level= MYSQL_ERROR::WARN_LEVEL_ERROR; + + m_sql_state[0]= '\0'; + m_message[0]= '\0'; + } +}; + + /* This class is a runtime context of a Stored Routine. It is used in an execution and is intended to contain all dynamic objects (i.e. objects, which @@ -146,8 +186,7 @@ class sp_rcontext : public Sql_alloc MYSQL_ERROR::enum_warning_level level, const char *msg); - MYSQL_ERROR * - raised_condition() const; + Sql_condition_info *raised_condition() const; void push_hstack(uint h); @@ -232,7 +271,7 @@ private: SQL conditions caught by each handler. This is an array indexed by handler index. */ - MYSQL_ERROR *m_raised_conditions; + Sql_condition_info *m_raised_conditions; uint m_hcount; // Stack pointer for m_handler uint *m_hstack; // Return stack for continue handlers diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9921969929d..f38f29898d3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -50,6 +50,7 @@ #include "sql_connect.h" #include "hostname.h" #include "sql_db.h" +#include "sql_array.h" bool mysql_user_table_is_in_short_password_format= false; @@ -570,8 +571,9 @@ enum enum_acl_lists COLUMN_PRIVILEGES_HASH, PROC_PRIVILEGES_HASH, FUNC_PRIVILEGES_HASH, - ACL_PROXY_USERS + PROXY_USERS_ACL }; + /* Convert scrambled password to binary form, according to scramble type, Binary form is stored in user.salt. @@ -2722,7 +2724,13 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, get_grantor(thd, grantor); - table->file->ha_index_init(0, 1); + if ((error= table->file->ha_index_init(0, 1))) + { + table->file->print_error(error, MYF(0)); + DBUG_PRINT("info", ("ha_index_init error")); + DBUG_RETURN(-1); + } + if (table->file->ha_index_read_map(table->record[0], user_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) @@ -2964,7 +2972,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len); col_privs->field[4]->store("",0, &my_charset_latin1); - col_privs->file->ha_index_init(0, 1); + if (col_privs->file->ha_index_init(0, 1)) + { + cols= 0; + return; + } + if (col_privs->file->ha_index_read_map(col_privs->record[0], (uchar*) key, (key_part_map)15, HA_READ_KEY_EXACT)) @@ -3104,7 +3117,7 @@ static int replace_column_table(GRANT_TABLE *g_t, const char *db, const char *table_name, ulong rights, bool revoke_grant) { - int error=0,result=0; + int result=0; uchar key[MAX_KEY_LENGTH]; uint key_prefix_length; KEY_PART_INFO *key_part= table->key_info->key_part; @@ -3131,7 +3144,13 @@ static int replace_column_table(GRANT_TABLE *g_t, List_iterator <LEX_COLUMN> iter(columns); class LEX_COLUMN *column; - table->file->ha_index_init(0, 1); + int error= table->file->ha_index_init(0, 1); + if (error) + { + table->file->print_error(error, MYF(0)); + DBUG_RETURN(-1); + } + while ((column= iter++)) { ulong privileges= column->rights; @@ -4257,7 +4276,10 @@ static my_bool grant_load_procs_priv(TABLE *p_table) (void) my_hash_init(&func_priv_hash, &my_charset_utf8_bin, 0,0,0, (my_hash_get_key) get_grant_table, 0,0); - p_table->file->ha_index_init(0, 1); + + if (p_table->file->ha_index_init(0, 1)) + DBUG_RETURN(TRUE); + p_table->use_all_columns(); if (!p_table->file->ha_index_first(p_table->record[0])) @@ -4358,7 +4380,10 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables) t_table = tables[0].table; c_table = tables[1].table; - t_table->file->ha_index_init(0, 1); + + if (t_table->file->ha_index_init(0, 1)) + goto end_index_init; + t_table->use_all_columns(); c_table->use_all_columns(); @@ -4403,9 +4428,10 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables) return_val=0; // Return ok end_unlock: - thd->variables.sql_mode= old_sql_mode; t_table->file->ha_index_end(); my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr); +end_index_init: + thd->variables.sql_mode= old_sql_mode; DBUG_RETURN(return_val); } @@ -6098,11 +6124,10 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, 2 COLUMN_PRIVILEGES_HASH 3 PROC_PRIVILEGES_HASH 4 FUNC_PRIVILEGES_HASH - 5 ACL_PROXY_USERS + 5 PROXY_USERS_ACL @retval > 0 At least one element matched. @retval 0 OK, but no element matched. - @retval -1 Wrong arguments to function or Out of Memory */ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, @@ -6147,10 +6172,11 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, grant_name_hash= &func_priv_hash; elements= grant_name_hash->records; break; - case 5: + case PROXY_USERS_ACL: elements= acl_proxy_users.elements; break; default: + DBUG_ASSERT(0); return -1; } @@ -6185,7 +6211,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, host= grant_name->host.hostname; break; - case 5: + case PROXY_USERS_ACL: acl_proxy_user= dynamic_element(&acl_proxy_users, idx, ACL_PROXY_USER*); user= acl_proxy_user->get_user(); host= acl_proxy_user->get_host(); @@ -6225,7 +6251,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, my_hash_delete(grant_name_hash, (uchar*) grant_name); break; - case 5: + case PROXY_USERS_ACL: delete_dynamic_element(&acl_proxy_users, idx); break; @@ -6297,11 +6323,10 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, break; } - case 5: + case PROXY_USERS_ACL: acl_proxy_user->set_user (&mem, user_to->user.str); acl_proxy_user->set_host (&mem, user_to->host.str); break; - } } else @@ -6448,7 +6473,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, /* Handle proxies_priv table. */ if (tables[5].table) { - if ((found= handle_grant_table(tables, ACL_PROXY_USERS, drop, user_from, user_to)) < 0) + if ((found= handle_grant_table(tables, 5, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ result= -1; @@ -6456,7 +6481,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle proxies_priv array. */ - if ((handle_grant_struct(ACL_PROXY_USERS, drop, user_from, user_to) && !result) || + if ((handle_grant_struct(PROXY_USERS_ACL, drop, user_from, user_to) && !result) || found) result= 1; /* At least one record/element found. */ } @@ -7278,14 +7303,25 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, DBUG_RETURN(FALSE); } - /* one can grant proxy to himself to others */ - if (!strcmp(thd->security_ctx->user, user) && + /* + one can grant proxy for self to others. + Security context in THD contains two pairs of (user,host): + 1. (user,host) pair referring to inbound connection. + 2. (priv_user,priv_host) pair obtained from mysql.user table after doing + authnetication of incoming connection. + Privileges should be checked wrt (priv_user, priv_host) tuple, because + (user,host) pair obtained from inbound connection may have different + values than what is actually stored in mysql.user table and while granting + or revoking proxy privilege, user is expected to provide entries mentioned + in mysql.user table. + */ + if (!strcmp(thd->security_ctx->priv_user, user) && !my_strcasecmp(system_charset_info, host, - thd->security_ctx->host)) + thd->security_ctx->priv_host)) { DBUG_PRINT("info", ("strcmp (%s, %s) my_casestrcmp (%s, %s) equal", - thd->security_ctx->user, user, - host, thd->security_ctx->host)); + thd->security_ctx->priv_user, user, + host, thd->security_ctx->priv_host)); DBUG_RETURN(FALSE); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index d03b38171fc..d779f679021 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -846,14 +846,14 @@ retry: case RFIRST: if (keyname) { - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); - error= table->file->ha_index_first(table->record[0]); + if (!(error= table->file->ha_index_or_rnd_end()) && + !(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_first(table->record[0]); } else { - table->file->ha_index_or_rnd_end(); - if (!(error= table->file->ha_rnd_init(1))) + if (!(error= table->file->ha_index_or_rnd_end()) && + !(error= table->file->ha_rnd_init(1))) error= table->file->ha_rnd_next(table->record[0]); } mode= RNEXT; @@ -872,10 +872,10 @@ retry: /* else fall through */ case RLAST: DBUG_ASSERT(keyname != 0); - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); - error= table->file->ha_index_last(table->record[0]); - mode= RPREV; + if (!(error= table->file->ha_index_or_rnd_end()) && + !(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_last(table->record[0]); + mode=RPREV; break; case RNEXT_SAME: /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */ @@ -889,13 +889,14 @@ retry: if (!(key= (uchar*) thd->calloc(ALIGN_SIZE(handler->key_len)))) goto err; - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); + if ((error= table->file->ha_index_or_rnd_end())) + break; key_copy(key, table->record[0], table->key_info + keyno, handler->key_len); - error= table->file->ha_index_read_map(table->record[0], - key, handler->keypart_map, - ha_rkey_mode); + if (!(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_read_map(table->record[0], + key, handler->keypart_map, + ha_rkey_mode); mode= rkey_to_rnext[(int)ha_rkey_mode]; break; } diff --git a/sql/sql_help.cc b/sql/sql_help.cc index c352272e95c..458904ebe1d 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -303,8 +303,14 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations, rtopic_id= find_fields[help_relation_help_topic_id].field; rkey_id= find_fields[help_relation_help_keyword_id].field; - topics->file->ha_index_init(iindex_topic,1); - relations->file->ha_index_init(iindex_relations,1); + if (topics->file->ha_index_init(iindex_topic,1) || + relations->file->ha_index_init(iindex_relations,1)) + { + if (topics->file->inited) + topics->file->ha_index_end(); + my_message(ER_CORRUPT_HELP_DB, ER(ER_CORRUPT_HELP_DB), MYF(0)); + DBUG_RETURN(-1); + } rkey_id->store((longlong) key_id, TRUE); rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2ae4adb4e33..255d03e69dd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6121,8 +6121,13 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->next_name_resolution_table= NULL; /* Link table in global list (all used tables) */ lex->add_to_query_tables(ptr); - ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type, - MDL_TRANSACTION); + + // Pure table aliases do not need to be locked: + if (!test(table_options & TL_OPTION_ALIAS)) + { + ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type, + MDL_TRANSACTION); + } DBUG_RETURN(ptr); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5995abc74f1..1146d37d06b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10610,7 +10610,6 @@ void JOIN::cleanup(bool full) filesort_free_buffers(first_tab->table, full); } } - if (full) { JOIN_TAB *sort_tab= first_linear_tab(this, WITHOUT_CONST_TABLES); @@ -15721,11 +15720,11 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) if (table->group && join->tmp_table_param.sum_func_count && table->s->keys && !table->file->inited) { - int tmp_error; - if ((tmp_error= table->file->ha_index_init(0, 0))) + rc= table->file->ha_index_init(0, 0); + if (rc) { - table->file->print_error(tmp_error, MYF(0)); /* purecov: inspected */ - DBUG_RETURN(-1); /* purecov: inspected */ + table->file->print_error(rc, MYF(0)); + DBUG_RETURN(-1); } } } @@ -16751,7 +16750,12 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref) int error; if (!table->file->inited) { - table->file->ha_index_init(table_ref->key, (tab ? tab->sorted : TRUE)); + error= table->file->ha_index_init(table_ref->key, tab ? tab->sorted : TRUE); + if (error) + { + (void) report_error(table, error); + return 1; + } } /* TODO: Why don't we do "Late NULLs Filtering" here? */ @@ -16842,8 +16846,8 @@ join_read_always_key(JOIN_TAB *tab) { if ((error= table->file->ha_index_init(tab->ref.key, tab->sorted))) { - table->file->print_error(error, MYF(0));/* purecov: inspected */ - return(1); /* purecov: inspected */ + (void) report_error(table, error); + return 1; } } @@ -16873,14 +16877,13 @@ join_read_last_key(JOIN_TAB *tab) int error; TABLE *table= tab->table; - if (!table->file->inited) + if (!table->file->inited && + (error= table->file->ha_index_init(tab->ref.key, tab->sorted))) { - if ((error= table->file->ha_index_init(tab->ref.key, tab->sorted))) - { - table->file->print_error(error, MYF(0));/* purecov: inspected */ - return(1); /* purecov: inspected */ - } + (void) report_error(table, error); + return 1; } + if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; if ((error= table->file->ha_index_read_map(table->record[0], @@ -17091,9 +17094,10 @@ join_ft_read_first(JOIN_TAB *tab) if (!table->file->inited && (error= table->file->ha_index_init(tab->ref.key, 1))) { - table->file->print_error(error, MYF(0)); /* purecov: inspected */ - return(1); /* purecov: inspected */ + (void) report_error(table, error); + return 1; } + table->file->ft_init(); if ((error= table->file->ha_ft_read(table->record[0]))) @@ -17498,9 +17502,10 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), /* Change method to update rows */ if ((error= table->file->ha_index_init(0, 0))) { - table->file->print_error(error, MYF(0));/* purecov: inspected */ - DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ + table->file->print_error(error, MYF(0)); + DBUG_RETURN(NESTED_LOOP_ERROR); } + join->join_tab[join->top_join_tab_count-1].next_select=end_unique_update; } join->send_records++; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6977b84524f..19146a146e4 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5668,7 +5668,13 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) { DBUG_RETURN(1); } - proc_table->file->ha_index_init(0, 1); + + if (proc_table->file->ha_index_init(0, 1)) + { + res= 1; + goto err; + } + if ((res= proc_table->file->ha_index_first(proc_table->record[0]))) { res= (res == HA_ERR_END_OF_FILE) ? 0 : 1; @@ -5694,7 +5700,9 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) } err: - proc_table->file->ha_index_end(); + if (proc_table->file->inited) + (void) proc_table->file->ha_index_end(); + close_system_tables(thd, &open_tables_state_backup); DBUG_RETURN(res); } diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc index c9f1f42159f..e671ad9526f 100644 --- a/sql/sql_signal.cc +++ b/sql/sql_signal.cc @@ -479,7 +479,7 @@ bool Signal_statement::execute(THD *thd) bool Resignal_statement::execute(THD *thd) { - MYSQL_ERROR *signaled; + Sql_condition_info *signaled; int result= TRUE; DBUG_ENTER("Resignal_statement::execute"); @@ -492,15 +492,21 @@ bool Resignal_statement::execute(THD *thd) DBUG_RETURN(result); } + MYSQL_ERROR signaled_err(thd->mem_root); + signaled_err.set(signaled->m_sql_errno, + signaled->m_sql_state, + signaled->m_level, + signaled->m_message); + if (m_cond == NULL) { /* RESIGNAL without signal_value */ - result= raise_condition(thd, signaled); + result= raise_condition(thd, &signaled_err); DBUG_RETURN(result); } /* RESIGNAL with signal_value */ - result= raise_condition(thd, signaled); + result= raise_condition(thd, &signaled_err); DBUG_RETURN(result); } diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 9d4ca5e1373..979dde30ceb 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -24,7 +24,7 @@ #include "sql_acl.h" // DROP_ACL #include "sql_parse.h" // check_one_table_access() #include "sql_truncate.h" -#include "sql_show.h" +#include "sql_show.h" //append_identifier() /** diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 78b693c5237..5836f7bf5dc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2241,11 +2241,16 @@ err: } err2: - (void) table->file->ha_rnd_end(); - (void) tmp_table->file->ha_rnd_end(); + if (table->file->inited) + (void) table->file->ha_rnd_end(); + if (tmp_table->file->inited) + (void) tmp_table->file->ha_rnd_end(); check_opt_it.rewind(); while (TABLE *tbl= check_opt_it++) - tbl->file->ha_rnd_end(); + { + if (tbl->file->inited) + (void) tbl->file->ha_rnd_end(); + } if (updated != org_updated) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 555efaf366d..253ec61460e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11454,11 +11454,19 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_AUTHORS; + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT, + ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT), + "SHOW AUTHORS"); } | CONTRIBUTORS_SYM { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS; + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT, + ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT), + "SHOW CONTRIBUTORS"); } | PRIVILEGES { diff --git a/sql/tztime.cc b/sql/tztime.cc index ba24cab9ca7..8194367a7f9 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1718,14 +1718,11 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) } table= tz_tables[0].table; - /* - It is OK to ignore ha_index_init()/ha_index_end() return values since - mysql.time_zone* tables are MyISAM and these operations always succeed - for MyISAM. - */ - (void)table->file->ha_index_init(0, 1); - table->use_all_columns(); + if (table->file->ha_index_init(0, 1)) + goto end_with_close; + + table->use_all_columns(); tz_leapcnt= 0; res= table->file->ha_index_first(table->record[0]); @@ -1913,12 +1910,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tz_tables= tz_tables->next_local; table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1); - /* - It is OK to ignore ha_index_init()/ha_index_end() return values since - mysql.time_zone* tables are MyISAM and these operations always succeed - for MyISAM. - */ - (void)table->file->ha_index_init(0, 1); + if (table->file->ha_index_init(0, 1)) + goto end; if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) @@ -1951,7 +1944,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) field->get_key_image(keybuff, min(field->key_length(), sizeof(keybuff)), Field::itRAW); - (void)table->file->ha_index_init(0, 1); + if (table->file->ha_index_init(0, 1)) + goto end; if (table->file->ha_index_read_map(table->record[0], keybuff, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) @@ -1983,7 +1977,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) field->get_key_image(keybuff, min(field->key_length(), sizeof(keybuff)), Field::itRAW); - (void)table->file->ha_index_init(0, 1); + if (table->file->ha_index_init(0, 1)) + goto end; res= table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT); @@ -2053,7 +2048,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) */ table= tz_tables->table; table->field[0]->store((longlong) tzid, TRUE); - (void)table->file->ha_index_init(0, 1); + if (table->file->ha_index_init(0, 1)) + goto end; res= table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT); @@ -2187,8 +2183,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) end: - if (table) - (void)table->file->ha_index_end(); + if (table && table->file->inited) + (void) table->file->ha_index_end(); DBUG_RETURN(return_val); } diff --git a/sql/uniques.cc b/sql/uniques.cc index ae50a1d3970..69de2844f5b 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -77,7 +77,10 @@ int unique_intersect_write_to_ptrs(uchar* key, element_count count, Unique *uniq Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, uint size_arg, ulonglong max_in_memory_size_arg, uint min_dupl_count_arg) - :max_in_memory_size(max_in_memory_size_arg), size(size_arg), elements(0) + :max_in_memory_size(max_in_memory_size_arg), + record_pointers(NULL), + size(size_arg), + elements(0) { min_dupl_count= min_dupl_count_arg; full_size= size; @@ -625,6 +628,7 @@ bool Unique::get(TABLE *table) if (my_b_tell(&file) == 0) { /* Whole tree is in memory; Don't use disk if you don't need to */ + DBUG_ASSERT(table->sort.record_pointers == NULL); if ((record_pointers=table->sort.record_pointers= (uchar*) my_malloc(size * tree.elements_in_tree, MYF(0)))) { @@ -650,6 +654,7 @@ bool Unique::get(TABLE *table) bool error=1; /* Open cached file if it isn't open */ + DBUG_ASSERT(table->sort.io_cache == NULL); outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), MYF(MY_ZEROFILL)); |