diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/filesort.cc | 2 | ||||
-rw-r--r-- | sql/gen_lex_hash.cc | 31 | ||||
-rw-r--r-- | sql/ha_partition.cc | 137 | ||||
-rw-r--r-- | sql/ha_partition.h | 12 | ||||
-rw-r--r-- | sql/handler.cc | 30 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 51 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 12 | ||||
-rw-r--r-- | sql/share/charsets/Index.xml | 2 | ||||
-rw-r--r-- | sql/spatial.cc | 7 | ||||
-rw-r--r-- | sql/spatial.h | 8 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 8 | ||||
-rw-r--r-- | sql/sql_select.cc | 15 | ||||
-rw-r--r-- | sql/sql_show.cc | 5 | ||||
-rw-r--r-- | sql/sql_string.h | 10 |
15 files changed, 208 insertions, 124 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index 46348f91bb4..a4d4ec1b37f 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, 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 diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 773345b36fe..c34647c8916 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, 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 @@ -89,6 +89,8 @@ So, we can read full search-structure as 32-bit word #include "mysql_version.h" #include "lex.h" +#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ + const char *default_dbug_option="d:t:o,/tmp/gen_lex_hash.trace"; struct my_option my_long_options[] = @@ -348,10 +350,7 @@ static void usage(int version) my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); if (version) return; - puts("Copyright (C) 2001 MySQL AB, by VVA and Monty"); - puts("Copyright (C) 2011 Oracle"); - puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ -and you are welcome to modify and redistribute it under the GPL license\n"); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("This program generates a perfect hashing function for the sql_lex.cc"); printf("Usage: %s [OPTIONS]\n\n", my_progname); my_print_help(my_long_options); @@ -453,25 +452,9 @@ int main(int argc,char **argv) /* Broken up to indicate that it's not advice to you, gentle reader. */ printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n"); - printf("\ -/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.\n\ - Copyright (C) 2008-2011 Oracle\n\ -\n\ - This program is free software; you can redistribute it and/or modify\n\ - it under the terms of the GNU General Public License as published by\n\ - the Free Software Foundation; version 2 of the License.\n\ -\n\ - This program is distributed in the hope that it will be useful,\n\ - but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ - GNU General Public License for more details.\n\ -\n\ - You should have received a copy of the GNU General Public License\n\ - along with this program; see the file COPYING. If not, write to the\n\ - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston\n\ - MA 02110-1301 USA. */\n\ -\n\ -"); + puts("/*"); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); + puts("*/"); /* Broken up to indicate that it's not advice to you, gentle reader. */ printf("/* Do " "not " "edit " "this " "file! This is generated by " diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 4dc581add99..bd57ead99bd 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -324,9 +324,7 @@ ha_partition::~ha_partition() for (i= 0; i < m_tot_parts; i++) delete m_file[i]; } - - my_free(m_ordered_rec_buffer, MYF(MY_ALLOW_ZERO_PTR)); - m_ordered_rec_buffer= NULL; + destroy_record_priority_queue(); clear_handler_file(); @@ -2656,7 +2654,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) { char *name_buffer_ptr; int error= HA_ERR_INITIALIZATION; - uint alloc_len; handler **file; char name_buff[FN_REFLEN]; bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE); @@ -2673,33 +2670,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) name_buffer_ptr= m_name_buffer_ptr; m_start_key.length= 0; m_rec0= table->record[0]; - m_rec_length= table_share->stored_rec_length; - alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS); - alloc_len+= table_share->max_key_length; - if (!m_ordered_rec_buffer) - { - if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME)))) - { - DBUG_RETURN(error); - } - { - /* - We set-up one record per partition and each record has 2 bytes in - front where the partition id is written. This is used by ordered - index_read. - We also set-up a reference to the first record for temporary use in - setting up the scan. - */ - char *ptr= (char*)m_ordered_rec_buffer; - uint i= 0; - do - { - int2store(ptr, i); - ptr+= m_rec_length + PARTITION_BYTES_IN_POS; - } while (++i < m_tot_parts); - m_start_key.key= (const uchar*)ptr; - } - } + m_rec_length= table_share->reclength; /* Initialize the bitmap we use to minimize ha_start_bulk_insert calls */ if (bitmap_init(&m_bulk_insert_started, NULL, m_tot_parts + 1, FALSE)) @@ -2719,7 +2690,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) if (m_is_clone_of) { - uint i; + uint i, alloc_len; DBUG_ASSERT(m_clone_mem_root); /* Allocate an array of handler pointers for the partitions handlers. */ alloc_len= (m_tot_parts + 1) * sizeof(handler*); @@ -2797,12 +2768,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) being opened once. */ clear_handler_file(); - /* - Initialize priority queue, initialized to reading forward. - */ - if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS, - 0, key_rec_cmp, (void*)this, 0, 0))) - goto err_handler; /* Use table_share->ha_data to share auto_increment_value among all handlers @@ -2925,7 +2890,7 @@ int ha_partition::close(void) DBUG_ENTER("ha_partition::close"); DBUG_ASSERT(table->s == table_share); - delete_queue(&m_queue); + destroy_record_priority_queue(); bitmap_free(&m_bulk_insert_started); if (!m_is_clone_of) bitmap_free(&(m_part_info->used_partitions)); @@ -4147,6 +4112,78 @@ int ha_partition::rnd_pos_by_record(uchar *record) subset of the partitions are used, then only use those partitions. */ + +/** + Setup the ordered record buffer and the priority queue. +*/ + +bool ha_partition::init_record_priority_queue() +{ + DBUG_ENTER("ha_partition::init_record_priority_queue"); + DBUG_ASSERT(!m_ordered_rec_buffer); + /* + Initialize the ordered record buffer. + */ + if (!m_ordered_rec_buffer) + { + uint alloc_len; + uint used_parts= bitmap_bits_set(&m_part_info->used_partitions); + /* Allocate record buffer for each used partition. */ + alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS); + /* Allocate a key for temporary use when setting up the scan. */ + alloc_len+= table_share->max_key_length; + + if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME)))) + DBUG_RETURN(true); + + /* + We set-up one record per partition and each record has 2 bytes in + front where the partition id is written. This is used by ordered + index_read. + We also set-up a reference to the first record for temporary use in + setting up the scan. + */ + char *ptr= (char*) m_ordered_rec_buffer; + uint16 i= 0; + do + { + if (bitmap_is_set(&m_part_info->used_partitions, i)) + { + int2store(ptr, i); + ptr+= m_rec_length + PARTITION_BYTES_IN_POS; + } + } while (++i < m_tot_parts); + m_start_key.key= (const uchar*)ptr; + /* Initialize priority queue, initialized to reading forward. */ + if (init_queue(&m_queue, used_parts, (uint) PARTITION_BYTES_IN_POS, + 0, key_rec_cmp, (void*)m_curr_key_info, 0, 0)) + { + my_free(m_ordered_rec_buffer, MYF(0)); + m_ordered_rec_buffer= NULL; + DBUG_RETURN(true); + } + } + DBUG_RETURN(false); +} + + +/** + Destroy the ordered record buffer and the priority queue. +*/ + +void ha_partition::destroy_record_priority_queue() +{ + DBUG_ENTER("ha_partition::destroy_record_priority_queue"); + if (m_ordered_rec_buffer) + { + delete_queue(&m_queue); + my_free(m_ordered_rec_buffer, MYF(0)); + m_ordered_rec_buffer= NULL; + } + DBUG_VOID_RETURN; +} + + /* Initialize handler before start of index scan @@ -4189,6 +4226,10 @@ int ha_partition::index_init(uint inx, bool sorted) } else m_curr_key_info[1]= NULL; + + if (init_record_priority_queue()) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + /* Some handlers only read fields as specified by the bitmap for the read set. For partitioned handlers we always require that the @@ -4263,11 +4304,11 @@ int ha_partition::index_end() do { int tmp; - /* TODO RONM: Change to index_end() when code is stable */ if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) if ((tmp= (*file)->ha_index_end())) error= tmp; } while (*(++file)); + destroy_record_priority_queue(); DBUG_RETURN(error); } @@ -4980,6 +5021,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) uint i; uint j= queue_first_element(&m_queue); bool found= FALSE; + uchar *part_rec_buf_ptr= m_ordered_rec_buffer; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); m_top_entry= NO_CURRENT_PART_ID; @@ -4990,7 +5032,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) { if (!(bitmap_is_set(&(m_part_info->used_partitions), i))) continue; - uchar *rec_buf_ptr= rec_buf(i); + uchar *rec_buf_ptr= part_rec_buf_ptr + PARTITION_BYTES_IN_POS; int error; handler *file= m_file[i]; @@ -5037,12 +5079,13 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) /* Initialize queue without order first, simply insert */ - queue_element(&m_queue, j++)= (uchar*)queue_buf(i); + queue_element(&m_queue, j++)= part_rec_buf_ptr; } else if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { DBUG_RETURN(error); } + part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS; } if (found) { @@ -5105,18 +5148,19 @@ 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]; DBUG_ENTER("ha_partition::handle_ordered_next"); if (m_index_scan_type == partition_read_range) { error= file->read_range_next(); - memcpy(rec_buf(part_id), table->record[0], m_rec_length); + memcpy(rec_buf, table->record[0], m_rec_length); } else if (!is_next_same) - error= file->ha_index_next(rec_buf(part_id)); + error= file->ha_index_next(rec_buf); else - error= file->ha_index_next_same(rec_buf(part_id), m_start_key.key, + error= file->ha_index_next_same(rec_buf, m_start_key.key, m_start_key.length); if (error) { @@ -5159,10 +5203,11 @@ int ha_partition::handle_ordered_prev(uchar *buf) { 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]; DBUG_ENTER("ha_partition::handle_ordered_prev"); - if ((error= file->ha_index_prev(rec_buf(part_id)))) + if ((error= file->ha_index_prev(rec_buf))) { if (error == HA_ERR_END_OF_FILE) { diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 8c01e4be34e..05461c12525 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -515,21 +515,13 @@ public: virtual int read_range_next(); private: + bool init_record_priority_queue(); + void destroy_record_priority_queue(); int common_index_read(uchar * buf, bool have_start_key); int common_first_last(uchar * buf); int partition_scan_set_up(uchar * buf, bool idx_read_flag); int handle_unordered_next(uchar * buf, bool next_same); int handle_unordered_scan_next_partition(uchar * buf); - uchar *queue_buf(uint part_id) - { - return (m_ordered_rec_buffer + - (part_id * (m_rec_length + PARTITION_BYTES_IN_POS))); - } - uchar *rec_buf(uint part_id) - { - return (queue_buf(part_id) + - PARTITION_BYTES_IN_POS); - } int handle_ordered_index_scan(uchar * buf, bool reverse_order); int handle_ordered_next(uchar * buf, bool next_same); int handle_ordered_prev(uchar * buf); diff --git a/sql/handler.cc b/sql/handler.cc index 5f3be58cfb2..ca6a958f2c5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4488,7 +4488,20 @@ int handler::read_range_first(const key_range *start_key, DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_END_OF_FILE : result); - DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); + + if (compare_key(end_range) <= 0) + { + DBUG_RETURN(0); + } + else + { + /* + The last read row does not fall in the range. So request + storage engine to release row lock if possible. + */ + unlock_row(); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } } @@ -4520,7 +4533,20 @@ int handler::read_range_next() result= ha_index_next(table->record[0]); if (result) DBUG_RETURN(result); - DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); + + if (compare_key(end_range) <= 0) + { + DBUG_RETURN(0); + } + else + { + /* + The last read row does not fall in the range. So request + storage engine to release row lock if possible. + */ + unlock_row(); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 23abc8a07cf..1b228a344f4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3050,23 +3050,21 @@ err: String* Item_func_export_set::val_str(String* str) { DBUG_ASSERT(fixed == 1); - ulonglong the_set = (ulonglong) args[0]->val_int(); - String yes_buf, *yes; - yes = args[1]->val_str(&yes_buf); - String no_buf, *no; - no = args[2]->val_str(&no_buf); - String *sep = NULL, sep_buf ; + String yes_buf, no_buf, sep_buf; + const ulonglong the_set = (ulonglong) args[0]->val_int(); + const String *yes= args[1]->val_str(&yes_buf); + const String *no= args[2]->val_str(&no_buf); + const String *sep= NULL; uint num_set_values = 64; - ulonglong mask = 0x1; str->length(0); str->set_charset(collation.collation); /* Check if some argument is a NULL value */ if (args[0]->null_value || args[1]->null_value || args[2]->null_value) { - null_value=1; - return 0; + null_value= true; + return NULL; } /* Arg count can only be 3, 4 or 5 here. This is guaranteed from the @@ -3079,37 +3077,56 @@ String* Item_func_export_set::val_str(String* str) num_set_values=64; if (args[4]->null_value) { - null_value=1; - return 0; + null_value= true; + return NULL; } /* Fall through */ case 4: if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL { - null_value=1; - return 0; + null_value= true; + return NULL; } break; case 3: { /* errors is not checked - assume "," can always be converted */ uint errors; - sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors); + sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, + collation.collation, &errors); sep = &sep_buf; } break; default: DBUG_ASSERT(0); // cannot happen } - null_value=0; + null_value= false; + + const ulong max_allowed_packet= current_thd->variables.max_allowed_packet; + const uint num_separators= num_set_values > 0 ? num_set_values - 1 : 0; + const ulonglong max_total_length= + num_set_values * max(yes->length(), no->length()) + + num_separators * sep->length(); + + if (unlikely(max_total_length > max_allowed_packet)) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_ALLOWED_PACKET_OVERFLOWED, + ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), + func_name(), max_allowed_packet); + null_value= true; + return NULL; + } - for (uint i = 0; i < num_set_values; i++, mask = (mask << 1)) + uint ix; + ulonglong mask; + for (ix= 0, mask=0x1; ix < num_set_values; ++ix, mask = (mask << 1)) { if (the_set & mask) str->append(*yes); else str->append(*no); - if (i != num_set_values - 1) + if (ix != num_separators) str->append(*sep); } return str; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6fc1a591594..a91efaec51f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1945,7 +1945,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, } else { - Item *item= (Item*) select_lex->item_list.head(); + Item *item= (Item*) select_lex->item_list.head()->real_item(); if (select_lex->table_list.elements) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5195fbde25b..0ebc03c0a4f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -272,6 +272,8 @@ extern "C" sig_handler handle_fatal_signal(int sig); /* Constants */ +#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE + const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; /* WARNING: When adding new SQL modes don't forget to update the @@ -8260,14 +8262,8 @@ static void usage(void) if (!default_collation_name) default_collation_name= (char*) default_charset_info->name; print_version(); - puts("\ -Copyright (C) 2000-2008 MySQL AB, by Monty and others.\n\ -Copyright (C) 2000, 2011 Oracle.\n\ -Copyright (C) 2009-2011 Monty Program Ab.\n\ -This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ -and you are welcome to modify and redistribute it under the GPL license\n\n\ -Starts the MariaDB database server.\n"); - + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); + puts("Starts the MariaDB database server.\n"); printf("Usage: %s [OPTIONS]\n", my_progname); if (!opt_verbose) puts("\nFor more help options (several pages), use mysqld --verbose --help."); diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 80b844e2f19..07e7e37b798 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -3,7 +3,7 @@ <charsets max-id="99"> <copyright> - Copyright (C) 2003 MySQL AB + Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/spatial.cc b/sql/spatial.cc index 44c5ea411b7..0da2fdf40b3 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -597,7 +597,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len, Gis_point p; if (len < 4 || - (n_points= wkb_get_uint(wkb, bo))<1) + (n_points= wkb_get_uint(wkb, bo)) < 1 || + n_points > max_n_points) return 0; proper_length= 4 + n_points * POINT_DATA_SIZE; @@ -1331,9 +1332,9 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, Gis_point p; const char *wkb_end; - if (len < 4) + if (len < 4 || + (n_points= wkb_get_uint(wkb, bo)) > max_n_points) return 0; - n_points= wkb_get_uint(wkb, bo); proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE); if (len < proper_size || res->reserve(proper_size)) diff --git a/sql/spatial.h b/sql/spatial.h index cd29b14ff38..6850cc804d0 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -390,6 +390,10 @@ public: class Gis_line_string: public Geometry { + // Maximum number of points in LineString that can fit into String + static const uint32 max_n_points= + (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + POINT_DATA_SIZE; public: Gis_line_string() {} /* Remove gcc warning */ virtual ~Gis_line_string() {} /* Remove gcc warning */ @@ -450,6 +454,10 @@ public: class Gis_multi_point: public Geometry { + // Maximum number of points in MultiPoint that can fit into String + static const uint32 max_n_points= + (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + (WKB_HEADER_SIZE + POINT_DATA_SIZE); public: Gis_multi_point() {} /* Remove gcc warning */ virtual ~Gis_multi_point() {} /* Remove gcc warning */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 52584ef3d18..9e8a6b941c6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -788,6 +788,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); if (param->state == Item_param::NO_VALUE) DBUG_RETURN(1); + + if (param->limit_clause_param && param->item_type != Item::INT_ITEM) + { + param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS); + param->item_type= Item::INT_ITEM; + if (!param->unsigned_flag && param->value.integer < 0) + DBUG_RETURN(1); + } } } /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c4dad7c16bf..bf01e42f3c0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -672,8 +672,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (having) { - Query_arena backup, *arena; - arena= thd->activate_stmt_arena_if_needed(&backup); nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->where="having clause"; thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level; @@ -690,8 +688,6 @@ JOIN::prepare(Item ***rref_pointer_array, having->check_cols(1))); select_lex->having_fix_field= 0; select_lex->having= having; - if (arena) - thd->restore_active_arena(arena, &backup); if (having_fix_rc || thd->is_error()) DBUG_RETURN(-1); /* purecov: inspected */ @@ -1599,12 +1595,19 @@ JOIN::optimize() DBUG_RETURN(1); } } - + /* + Calculate a possible 'limit' of table rows for 'GROUP BY': 'need_tmp' + implies that there will be more postprocessing so the specified + 'limit' should not be enforced yet in the call to + 'test_if_skip_sort_order'. + */ + const ha_rows limit = need_tmp ? HA_POS_ERROR : unit->select_limit_cnt; + if (!(select_options & SELECT_BIG_RESULT) && ((group_list && (!simple_group || !test_if_skip_sort_order(&join_tab[const_tables], group_list, - unit->select_limit_cnt, 0, + limit, 0, &join_tab[const_tables].table-> keys_in_use_for_group_by))) || select_distinct) && diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e01e75db00f..13ead720438 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3906,8 +3906,9 @@ end: /* Restore original LEX value, statement's arena and THD arena values. */ lex_end(thd->lex); - if (i_s_arena.free_list) - i_s_arena.free_items(); + // Free items, before restoring backup_arena below. + DBUG_ASSERT(i_s_arena.free_list == NULL); + thd->free_items(); /* For safety reset list of open temporary tables before closing diff --git a/sql/sql_string.h b/sql/sql_string.h index 9e596866de1..61003774ecc 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2008-2011 Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -263,8 +263,12 @@ public: return 0; return realloc_with_extra(arg_length); } - inline void shrink(uint32 arg_length) // Shrink buffer + + // Shrink the buffer, but only if it is allocated on the heap. + inline void shrink(uint32 arg_length) { + if (!is_alloced()) + return; if (ALIGN_SIZE(arg_length+1) < Alloced_length) { char *new_ptr; @@ -280,7 +284,7 @@ public: } } } - bool is_alloced() { return alloced; } + bool is_alloced() const { return alloced; } inline String& operator = (const String &s) { if (&s != this) |