summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <timour@askmonty.org>2012-11-08 15:24:35 +0200
committerunknown <timour@askmonty.org>2012-11-08 15:24:35 +0200
commitc5cef4b1664faf134611f1d94ace7efc0bb93ebd (patch)
tree291e9a80b2b240953ae531bb645eaa10a9bf1aa3 /sql
parenta00688a7154ac87dff82f15810ebec9ec577e0f0 (diff)
parent7c23d6d0c66cb3b84cb466f956e19bfea0acc342 (diff)
downloadmariadb-git-c5cef4b1664faf134611f1d94ace7efc0bb93ebd.tar.gz
Merge MariaDB 5.1.66 -> 5.2.12
Diffstat (limited to 'sql')
-rw-r--r--sql/filesort.cc5
-rw-r--r--sql/gen_lex_hash.cc31
-rw-r--r--sql/ha_partition.cc137
-rw-r--r--sql/ha_partition.h12
-rw-r--r--sql/handler.cc30
-rw-r--r--sql/item_strfunc.cc51
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/log_event.h2
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/share/charsets/Index.xml2
-rw-r--r--sql/spatial.cc11
-rw-r--r--sql/spatial.h8
-rw-r--r--sql/sql_prepare.cc8
-rw-r--r--sql/sql_select.cc15
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_string.h10
16 files changed, 212 insertions, 129 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 6445fa0f0fa..2ebfb59fa32 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
@@ -296,8 +296,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
Use also the space previously used by string pointers in sort_buffer
for temporary key storage.
*/
- param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
- param.rec_length-1);
+ param.keys= table_sort.sort_keys_size / param.rec_length;
maxbuffer--; // Offset from 0
if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
&tempfile))
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 1ff2f9ca78d..a209dafd1fe 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -325,9 +325,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();
@@ -2664,7 +2662,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);
@@ -2681,33 +2678,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))
@@ -2727,7 +2698,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*);
@@ -2805,12 +2776,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)))
- goto err_handler;
/*
Use table_share->ha_data to share auto_increment_value among all handlers
@@ -2933,7 +2898,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));
@@ -4153,6 +4118,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))
+ {
+ 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
@@ -4194,6 +4231,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
@@ -4268,11 +4309,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);
}
@@ -4985,6 +5026,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
uint i;
uint j= 0;
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;
@@ -4995,7 +5037,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];
@@ -5036,12 +5078,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)
{
@@ -5104,18 +5147,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)
{
@@ -5158,10 +5202,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 b1e38e0421d..c33216047b3 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -516,21 +516,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 a5dbf5170b7..86e584d4e1f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4521,7 +4521,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);
+ }
}
@@ -4553,7 +4566,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 1488fe25fd9..68b54609193 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3049,23 +3049,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
@@ -3078,37 +3076,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 888c346c199..55db3c6136f 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1171,7 +1171,7 @@ Item_in_subselect::single_value_transformer(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/log_event.h b/sql/log_event.h
index ddf0141c832..b78d674dba9 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2502,7 +2502,7 @@ public:
User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
char *val_arg, ulong val_len_arg, Item_result type_arg,
uint charset_number_arg)
- :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
+ :Log_event(thd_arg,0,0), name(name_arg), name_len(name_len_arg), val(val_arg),
val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
deferred(false)
{ is_null= !val; }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 39be34bab0c..b7544ac8f52 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -270,6 +270,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
@@ -8084,14 +8086,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 783d37ada48..eec028eaef1 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -525,12 +525,13 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
const char *wkb_end;
Gis_point p;
- if (len < 4)
+ if (len < 4 ||
+ (n_points= wkb_get_uint(wkb, bo)) < 1 ||
+ n_points > max_n_points)
return 0;
- n_points= wkb_get_uint(wkb, bo);
proper_length= 4 + n_points * POINT_DATA_SIZE;
- if (!n_points || len < proper_length || res->reserve(proper_length))
+ if (len < proper_length || res->reserve(proper_length))
return 0;
res->q_append(n_points);
@@ -1072,9 +1073,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 662c377dc1d..20b3856ca9a 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -379,6 +379,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 */
@@ -435,6 +439,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 6a36bca6a95..c269b262ff4 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -786,6 +786,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 cc377500b2c..87fb2ac95ad 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -538,8 +538,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;
@@ -549,8 +547,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 */
@@ -1468,12 +1464,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 69b6399fd62..795b009a551 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3585,8 +3585,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 f1b77d754c2..4b0aaff35b9 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
@@ -251,8 +251,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;
@@ -268,7 +272,7 @@ public:
}
}
}
- bool is_alloced() { return alloced; }
+ bool is_alloced() const { return alloced; }
inline String& operator = (const String &s)
{
if (&s != this)