#At file:///export/home/didrik/repo/trunk-bug11765255-arraycheck/ based on revid:vasil.dimov@stripped
3232 Tor Didriksen 2011-06-23
Bug#12590211 - ADD BOUNDS CHECK ON REF_POINTER_ARRAY AND FRIENDS
Cleanup the Item** and Item*** code for ref_pointer_array.
Wrap the array(s) in a container, so we can do bounds checks.
@ sql/item.cc
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item.h
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_cmpfunc.cc
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_cmpfunc.h
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_func.cc
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_func.h
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_row.cc
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_row.h
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_strfunc.cc
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_strfunc.h
Introduce Ref_ptr_array for split_sum_funcN functions.
@ sql/item_subselect.cc
Don't use select_lex->ref_pointer_array, use the "slice" owned by the JOIN instance instead.
@ sql/sql_array.h
New, templatized, array class.
@ sql/sql_derived.cc
Remove ref_pointer_array from mysql_select() function signature.
@ sql/sql_lex.cc
In setup_ref_array(), add sanity check that that the size of ref_pointer_array
does not change.
@ sql/sql_parse.cc
Remove ref_pointer_array from mysql_select() function signature.
@ sql/sql_select.cc
Changed several functions from
xx_(.. Item ** ..) to xx_(.. Ref_ptr_array ..)
Remove ref_pointer_array from mysql_select() function signature.
@ sql/sql_select.h
Document usage of ref_pointer_array.
Change from Item** to Ref_ptr_array.
Re-wrote setter functions.
@ sql/sql_union.cc
For UNION, the 'n_sum_items' are accumulated in the "global_parameters" select_lex.
This number must be propagated to setup_ref_array()
When preparing a 'fake_select_lex' we need to use global_parameters->order_list
rather than fake_select_lex->order_list (see comments inside st_select_lex_unit::cleanup)
@ sql/sql_yacc.yy
Reset parsing_place when done parsing 'SHOW' and 'DESCRIBE'
@ unittest/gunit/bounds_checked_array-t.cc
New unit test.
added:
unittest/gunit/bounds_checked_array-t.cc
modified:
sql/item.cc
sql/item.h
sql/item_cmpfunc.cc
sql/item_cmpfunc.h
sql/item_func.cc
sql/item_func.h
sql/item_row.cc
sql/item_row.h
sql/item_strfunc.cc
sql/item_strfunc.h
sql/item_subselect.cc
sql/item_sum.cc
sql/sql_array.h
sql/sql_base.cc
sql/sql_base.h
sql/sql_derived.cc
sql/sql_do.cc
sql/sql_insert.cc
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_load.cc
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_select.cc
sql/sql_select.h
sql/sql_union.cc
sql/sql_update.cc
sql/sql_yacc.yy
unittest/gunit/CMakeLists.txt
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2011-06-06 12:49:55 +0000
+++ b/sql/item.cc 2011-06-23 10:08:08 +0000
@@ -1489,7 +1489,7 @@ public:
thd->fatal_error() may be called if we are out of memory
*/
-void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
+void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, Item **ref,
bool skip_registered)
{
@@ -1526,7 +1526,7 @@ void Item::split_sum_func2(THD *thd, Ite
ref_pointer_array[el]= real_itm;
if (!(item_ref= new Item_aggregate_ref(&thd->lex->current_select->context,
- ref_pointer_array + el, 0, name)))
+ &ref_pointer_array[el], 0, name)))
return; // fatal_error is set
if (type() == SUM_FUNC_ITEM)
item_ref->depended_from= ((Item_sum *) this)->depended_from();
@@ -4345,7 +4345,7 @@ resolve_ref_in_select_and_group(THD *thd
return NULL;
}
DBUG_ASSERT((*select_ref)->fixed);
- return (select->ref_pointer_array + counter);
+ return &select->ref_pointer_array[counter];
}
if (group_by_ref)
return group_by_ref;
@@ -6233,13 +6233,13 @@ Item *Item_field::update_value_transform
type() != Item::TRIGGER_FIELD_ITEM)
{
List<Item> *all_fields= &select->join->all_fields;
- Item **ref_pointer_array= select->ref_pointer_array;
+ Ref_ptr_array &ref_pointer_array= select->ref_pointer_array;
int el= all_fields->elements;
Item_ref *ref;
ref_pointer_array[el]= (Item*)this;
all_fields->push_front((Item*)this);
- ref= new Item_ref(&select->context, ref_pointer_array + el,
+ ref= new Item_ref(&select->context, &ref_pointer_array[el],
table_name, field_name);
return ref;
}
=== modified file 'sql/item.h'
--- a/sql/item.h 2011-06-10 15:29:04 +0000
+++ b/sql/item.h 2011-06-23 10:08:08 +0000
@@ -23,6 +23,7 @@
#include "unireg.h" // REQUIRED: for other includes
#include "thr_malloc.h" /* sql_calloc */
#include "field.h" /* Derivation */
+#include "sql_array.h"
class Protocol;
struct TABLE_LIST;
@@ -30,6 +31,7 @@ void item_init(void); /* Init item fun
class Item_field;
class user_var_entry;
+typedef Bounds_checked_array<Item*> Ref_ptr_array;
static inline uint32
char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg)
@@ -932,10 +934,11 @@ public:
void print_item_w_name(String *, enum_query_type query_type);
virtual void update_used_tables() {}
- virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
+ virtual void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields) {}
/* Called for items that really have to be split */
- void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields,
+ void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
+ List<Item> &fields,
Item **ref, bool skip_registered);
virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
virtual bool get_time(MYSQL_TIME *ltime);
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2011-06-09 06:22:39 +0000
+++ b/sql/item_cmpfunc.cc 2011-06-23 10:08:08 +0000
@@ -4591,7 +4591,7 @@ void Item_cond::traverse_cond(Cond_trave
that have or refer (HAVING) to a SUM expression.
*/
-void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_cond::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields)
{
List_iterator<Item> li(list);
=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h 2011-06-09 06:22:39 +0000
+++ b/sql/item_cmpfunc.h 2011-06-23 10:08:08 +0000
@@ -1540,7 +1540,8 @@ public:
table_map used_tables() const;
void update_used_tables();
virtual void print(String *str, enum_query_type query_type);
- void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+ void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+ List<Item> &fields);
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
Item **conds);
void top_level_item() { abort_on_null=1; }
=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc 2011-06-09 06:22:39 +0000
+++ b/sql/item_func.cc 2011-06-23 10:08:08 +0000
@@ -392,7 +392,7 @@ Item *Item_func::compile(Item_analyzer a
See comments in Item_cmp_func::split_sum_func()
*/
-void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_func::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields)
{
Item **arg, **arg_end;
=== modified file 'sql/item_func.h'
--- a/sql/item_func.h 2011-05-05 07:41:53 +0000
+++ b/sql/item_func.h 2011-06-23 10:08:08 +0000
@@ -135,7 +135,8 @@ public:
void set_arguments(List<Item> &list);
inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; }
- void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+ void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+ List<Item> &fields);
virtual void print(String *str, enum_query_type query_type);
void print_op(String *str, enum_query_type query_type);
void print_args(String *str, uint from, enum_query_type query_type);
=== modified file 'sql/item_row.cc'
--- a/sql/item_row.cc 2011-06-09 06:22:39 +0000
+++ b/sql/item_row.cc 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, 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
@@ -113,7 +113,7 @@ void Item_row::cleanup()
}
-void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_row::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields)
{
Item **arg, **arg_end;
=== modified file 'sql/item_row.h'
--- a/sql/item_row.h 2010-10-15 10:32:50 +0000
+++ b/sql/item_row.h 2011-06-23 10:08:08 +0000
@@ -66,7 +66,8 @@ public:
void fix_after_pullout(st_select_lex *parent_select,
st_select_lex *removed_select, Item **ref);
void cleanup();
- void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+ void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+ List<Item> &fields);
table_map used_tables() const { return used_tables_cache; };
bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc 2011-06-09 06:22:39 +0000
+++ b/sql/item_strfunc.cc 2011-06-23 10:08:08 +0000
@@ -2540,7 +2540,8 @@ String *Item_func_elt::val_str(String *s
}
-void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_func_make_set::split_sum_func(THD *thd,
+ Ref_ptr_array ref_pointer_array,
List<Item> &fields)
{
item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE);
=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h 2011-04-15 09:04:21 +0000
+++ b/sql/item_strfunc.h 2011-06-23 10:08:08 +0000
@@ -556,7 +556,8 @@ public:
item->check_cols(1) ||
Item_func::fix_fields(thd, ref));
}
- void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+ void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+ List<Item> &fields);
void fix_length_and_dec();
void update_used_tables();
const char *func_name() const { return "make_set"; }
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2011-05-24 09:36:11 +0000
+++ b/sql/item_subselect.cc 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2002, 2011, 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
@@ -1126,7 +1126,7 @@ Item_in_subselect::single_value_transfor
(ALL && (> || =>)) || (ANY && (< || =<))
for ALL condition is inverted
*/
- item= new Item_sum_max(*select_lex->ref_pointer_array);
+ item= new Item_sum_max(join->ref_ptrs[0]);
}
else
{
@@ -1134,11 +1134,11 @@ Item_in_subselect::single_value_transfor
(ALL && (< || =<)) || (ANY && (> || =>))
for ALL condition is inverted
*/
- item= new Item_sum_min(*select_lex->ref_pointer_array);
+ item= new Item_sum_min(join->ref_ptrs[0]);
}
if (upper_item)
upper_item->set_sum_test(item);
- *select_lex->ref_pointer_array= item;
+ join->ref_ptrs[0]= item;
{
List_iterator<Item> it(select_lex->item_list);
it++;
@@ -1220,7 +1220,8 @@ Item_in_subselect::single_value_transfor
DBUG_RETURN(RES_OK);
/* Perform the IN=>EXISTS transformation. */
- DBUG_RETURN(single_value_in_to_exists_transformer(join, func));
+ const trans_res retval= single_value_in_to_exists_transformer(join, func);
+ DBUG_RETURN(retval);
}
@@ -1274,8 +1275,7 @@ Item_in_subselect::single_value_in_to_ex
Item *item= func->create(expr,
new Item_ref_null_helper(&select_lex->context,
this,
- select_lex->
- ref_pointer_array,
+ &join->ref_ptrs[0],
(char *)"<ref>",
this->full_name()));
if (!abort_on_null && left_expr->maybe_null)
@@ -1318,7 +1318,7 @@ Item_in_subselect::single_value_in_to_ex
select_lex->item_list.push_back(new Item_int("Not_used",
(longlong) 1,
MY_INT64_NUM_DECIMAL_DIGITS));
- select_lex->ref_pointer_array[0]= select_lex->item_list.head();
+ join->ref_ptrs[0]= select_lex->item_list.head();
item= func->create(expr, item);
if (!abort_on_null && orig_item->maybe_null)
@@ -1393,7 +1393,7 @@ Item_in_subselect::single_value_in_to_ex
Item *new_having=
func->create(expr,
new Item_ref_null_helper(&select_lex->context, this,
- select_lex->ref_pointer_array,
+ &join->ref_ptrs[0],
(char *)"<no matter>",
(char *)"<result>"));
if (!abort_on_null && left_expr->maybe_null)
@@ -1553,13 +1553,12 @@ Item_in_subselect::row_value_in_to_exist
Item *item_having_part2= 0;
for (uint i= 0; i < cols_num; i++)
{
- DBUG_ASSERT((left_expr->fixed &&
- select_lex->ref_pointer_array[i]->fixed) ||
- (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
- ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
- Item_ref::OUTER_REF));
- if (select_lex->ref_pointer_array[i]->
- check_cols(left_expr->element_index(i)->cols()))
+ Item *item_i= join->ref_ptrs[i];
+ Item **pitem_i= &join->ref_ptrs[i];
+ DBUG_ASSERT((left_expr->fixed && item_i->fixed) ||
+ (item_i->type() == REF_ITEM &&
+ ((Item_ref*)(item_i))->ref_type() == Item_ref::OUTER_REF));
+ if (item_i-> check_cols(left_expr->element_index(i)->cols()))
DBUG_RETURN(RES_ERROR);
Item *item_eq=
new Item_func_eq(new
@@ -1570,14 +1569,14 @@ Item_in_subselect::row_value_in_to_exist
(char *)in_left_expr_name),
new
Item_ref(&select_lex->context,
- select_lex->ref_pointer_array + i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>")
);
Item *item_isnull=
new Item_func_isnull(new
Item_ref(&select_lex->context,
- select_lex->ref_pointer_array+i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>")
);
@@ -1592,8 +1591,7 @@ Item_in_subselect::row_value_in_to_exist
Item *item_nnull_test=
new Item_is_not_null_test(this,
new Item_ref(&select_lex->context,
- select_lex->
- ref_pointer_array + i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>"));
if (!abort_on_null && left_expr->element_index(i)->maybe_null)
@@ -1630,16 +1628,14 @@ Item_in_subselect::row_value_in_to_exist
Item *where_item= 0;
for (uint i= 0; i < cols_num; i++)
{
- Item *item, *item_isnull;
- DBUG_ASSERT((left_expr->fixed &&
- select_lex->ref_pointer_array[i]->fixed) ||
- (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
- ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
- Item_ref::OUTER_REF));
- if (select_lex->ref_pointer_array[i]->
- check_cols(left_expr->element_index(i)->cols()))
+ Item *item_i= join->ref_ptrs[i];
+ Item **pitem_i= &join->ref_ptrs[i];
+ DBUG_ASSERT((left_expr->fixed && item_i->fixed) ||
+ (item_i->type() == REF_ITEM &&
+ ((Item_ref*)(item_i))->ref_type() == Item_ref::OUTER_REF));
+ if (item_i->check_cols(left_expr->element_index(i)->cols()))
DBUG_RETURN(RES_ERROR);
- item=
+ Item *item=
new Item_func_eq(new
Item_direct_ref(&select_lex->context,
(*optimizer->get_cache())->
@@ -1648,8 +1644,7 @@ Item_in_subselect::row_value_in_to_exist
(char *)in_left_expr_name),
new
Item_direct_ref(&select_lex->context,
- select_lex->
- ref_pointer_array+i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>")
);
@@ -1659,16 +1654,15 @@ Item_in_subselect::row_value_in_to_exist
new Item_is_not_null_test(this,
new
Item_ref(&select_lex->context,
- select_lex->ref_pointer_array + i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>"));
- item_isnull= new
+ Item *item_isnull= new
Item_func_isnull(new
Item_direct_ref(&select_lex->context,
- select_lex->
- ref_pointer_array+i,
+ pitem_i,
(char *)"<no matter>",
(char *)"<list ref>")
);
@@ -2155,8 +2149,7 @@ bool subselect_single_select_engine::pre
prepared= 1;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
- if (join->prepare(&select_lex->ref_pointer_array,
- select_lex->table_list.first,
+ if (join->prepare(select_lex->table_list.first,
select_lex->with_wild,
select_lex->where,
select_lex->order_list.elements +
=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc 2011-06-09 06:22:39 +0000
+++ b/sql/item_sum.cc 2011-06-23 10:08:08 +0000
@@ -3308,7 +3308,8 @@ bool Item_func_group_concat::setup(THD *
tmp table columns.
*/
if (arg_count_order &&
- setup_order(thd, args, context->table_list, list, all_fields, *order))
+ setup_order(thd, Ref_ptr_array(args, arg_count),
+ context->table_list, list, all_fields, *order))
DBUG_RETURN(TRUE);
count_field_types(select_lex, tmp_table_param, all_fields, 0);
=== modified file 'sql/sql_array.h'
--- a/sql/sql_array.h 2011-05-18 13:12:02 +0000
+++ b/sql/sql_array.h 2011-06-23 10:08:08 +0000
@@ -1,7 +1,7 @@
#ifndef SQL_ARRAY_INCLUDED
#define SQL_ARRAY_INCLUDED
-/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2003, 2011, 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
@@ -18,6 +18,60 @@
#include <my_sys.h>
+/**
+ A wrapper class which provides array bounds checking.
+ We do *not* own the array, we simply have a pointer to the first element,
+ and a length.
+
+ @remark
+ We want the compiler-generated versions of:
+ - the copy CTOR (memberwise initialization)
+ - the assignment operator (memberwise assignment)
+
+ @param Element_type The type of the elements of the container.
+ */
+template <typename Element_type> class Bounds_checked_array
+{
+public:
+ Bounds_checked_array() : m_array(NULL), m_size(0) {}
+
+ Bounds_checked_array(Element_type *el, size_t size)
+ : m_array(el), m_size(size)
+ {}
+
+ void reset() { m_array= NULL; m_size= 0; }
+
+ Element_type &operator[](size_t n)
+ {
+ DBUG_ASSERT(n < m_size);
+ return m_array[n];
+ }
+
+ const Element_type &operator[](size_t n) const
+ {
+ DBUG_ASSERT(n < m_size);
+ return m_array[n];
+ }
+
+ size_t element_size() const { return sizeof(Element_type); }
+ size_t size() const { return m_size; }
+
+ bool is_empty() const { return m_array == NULL; }
+
+ void pop_front()
+ {
+ DBUG_ASSERT(m_size > 0);
+ m_array+= 1;
+ m_size-= 1;
+ }
+
+ Element_type *array() const { return m_array; }
+
+private:
+ Element_type *m_array;
+ size_t m_size;
+};
+
/*
A typesafe wrapper around DYNAMIC_ARRAY
*/
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2011-06-15 22:31:43 +0000
+++ b/sql/sql_base.cc 2011-06-23 10:08:08 +0000
@@ -8025,7 +8025,7 @@ int setup_wild(THD *thd, TABLE_LIST *tab
** Check that all given fields exists and fill struct with current data
****************************************************************************/
-bool setup_fields(THD *thd, Item **ref_pointer_array,
+bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func)
{
@@ -8055,8 +8055,11 @@ bool setup_fields(THD *thd, Item **ref_p
TODO: remove it when (if) we made one list for allfields and
ref_pointer_array
*/
- if (ref_pointer_array)
- memset(ref_pointer_array, 0, sizeof(Item *) * fields.elements);
+ if (!ref_pointer_array.is_empty())
+ {
+ DBUG_ASSERT(ref_pointer_array.size() >= fields.elements);
+ memset(ref_pointer_array.array(), 0, sizeof(Item *) * fields.elements);
+ }
/*
We call set_entry() there (before fix_fields() of the whole list of field
@@ -8074,7 +8077,7 @@ bool setup_fields(THD *thd, Item **ref_p
while ((var= li++))
var->set_entry(thd, FALSE);
- Item **ref= ref_pointer_array;
+ Ref_ptr_array ref= ref_pointer_array;
thd->lex->current_select->cur_pos_in_select_list= 0;
while ((item= it++))
{
@@ -8087,8 +8090,11 @@ bool setup_fields(THD *thd, Item **ref_p
DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
DBUG_RETURN(TRUE); /* purecov: inspected */
}
- if (ref)
- *(ref++)= item;
+ if (!ref.is_empty())
+ {
+ ref[0]= item;
+ ref.pop_front();
+ }
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h 2011-05-04 07:51:15 +0000
+++ b/sql/sql_base.h 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2011, 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
@@ -184,7 +184,7 @@ bool insert_fields(THD *thd, Name_resolu
List_iterator<Item> *it, bool any_privileges);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
-bool setup_fields(THD *thd, Item** ref_pointer_array,
+bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func);
bool fill_record(THD *thd, Field **field, List<Item> &values,
@@ -350,7 +350,7 @@ inline TABLE_LIST *find_table_in_local_l
}
-inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
+inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &item,
enum_mark_columns mark_used_columns,
List<Item> *sum_func_list,
=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc 2011-06-09 08:58:41 +0000
+++ b/sql/sql_derived.cc 2011-06-23 10:08:08 +0000
@@ -286,7 +286,7 @@ bool mysql_derived_filling(THD *thd, LEX
first_select->options&= ~OPTION_FOUND_ROWS;
lex->current_select= first_select;
- res= mysql_select(thd, &first_select->ref_pointer_array,
+ res= mysql_select(thd,
first_select->table_list.first,
first_select->with_wild,
first_select->item_list, first_select->where,
=== modified file 'sql/sql_do.cc'
--- a/sql/sql_do.cc 2010-07-27 15:01:56 +0000
+++ b/sql/sql_do.cc 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, 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
@@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List<Item> &valu
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
- if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0))
DBUG_RETURN(TRUE);
while ((value = li++))
value->val_int();
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2011-06-10 16:57:01 +0000
+++ b/sql/sql_insert.cc 2011-06-23 10:08:08 +0000
@@ -256,7 +256,7 @@ static int check_insert_fields(THD *thd,
*/
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
- res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0);
+ res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0);
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
@@ -347,7 +347,8 @@ static int check_update_fields(THD *thd,
}
/* Check the fields we are going to modify */
- if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ update_fields, MARK_COLUMNS_WRITE, 0, 0))
return -1;
if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE &&
@@ -762,7 +763,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto abort;
}
- if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0))
goto abort;
}
its.rewind ();
@@ -1377,7 +1378,8 @@ bool mysql_prepare_insert(THD *thd, TABL
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
- res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0) ||
+ res= (setup_fields(thd, Ref_ptr_array(),
+ *values, MARK_COLUMNS_READ, 0, 0) ||
check_insert_fields(thd, context->table_list, fields, *values,
!insert_into_view, 0, &map));
@@ -1393,7 +1395,8 @@ bool mysql_prepare_insert(THD *thd, TABL
}
if (!res)
- res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0);
+ res= setup_fields(thd, Ref_ptr_array(),
+ update_values, MARK_COLUMNS_READ, 0, 0);
if (!res && duplic == DUP_UPDATE)
{
@@ -3234,7 +3237,7 @@ select_insert::prepare(List<Item> &value
/* Errors during check_insert_fields() should not be ignored. */
lex->current_select->no_error= FALSE;
- res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) ||
+ res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) ||
check_insert_fields(thd, table_list, *fields, values,
!insert_into_view, 1, &map));
@@ -3282,7 +3285,7 @@ select_insert::prepare(List<Item> &value
table_list->next_name_resolution_table=
ctx_state.get_first_name_resolution_table();
- res= res || setup_fields(thd, 0, *info.update_values,
+ res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values,
MARK_COLUMNS_READ, 0, 0);
if (!res)
{
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2011-06-10 09:52:57 +0000
+++ b/sql/sql_lex.cc 2011-06-23 10:08:08 +0000
@@ -1759,7 +1759,7 @@ void st_select_lex::init_query()
parent_lex->push_context(&context);
cond_count= between_count= with_wild= 0;
max_equal_elems= 0;
- ref_pointer_array= 0;
+ ref_pointer_array.reset();
select_n_where_fields= 0;
select_n_having_items= 0;
subquery_in_having= explicit_limit= 0;
@@ -2136,20 +2136,42 @@ ulong st_select_lex::get_table_join_opti
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
- if (ref_pointer_array)
- return 0;
+#ifdef DBUG_OFF
+ if (!ref_pointer_array.is_empty())
+ return false;
+#endif
+
+ // find_order_in_list() may need some extra space, so multiply by two.
+ order_group_num*= 2;
/*
We have to create array in prepared statement memory if it is
prepared statement
*/
Query_arena *arena= thd->stmt_arena;
- return (ref_pointer_array=
- (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
- item_list.elements +
- select_n_having_items +
- select_n_where_fields +
- order_group_num)*5)) == 0;
+ const uint n_elems= (n_child_sum_items +
+ item_list.elements +
+ select_n_having_items +
+ select_n_where_fields +
+ order_group_num) * 5;
+ DBUG_PRINT("info", ("setup_ref_array this %p %4u : %4u %4u %4u %4u %4u %4u",
+ this,
+ n_elems, // :
+ n_sum_items,
+ n_child_sum_items,
+ item_list.elements,
+ select_n_having_items,
+ select_n_where_fields,
+ order_group_num));
+ if (!ref_pointer_array.is_empty())
+ {
+ DBUG_ASSERT(ref_pointer_array.size() == n_elems);
+ return false;
+ }
+ Item **array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems));
+ ref_pointer_array= Ref_ptr_array(array, n_elems);
+
+ return array == NULL;
}
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2011-06-10 09:52:57 +0000
+++ b/sql/sql_lex.h 2011-06-23 10:08:08 +0000
@@ -24,6 +24,7 @@
#include "sql_trigger.h"
#include "item.h" /* From item_subselect.h: subselect_union_engine */
#include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */
+#include "sql_array.h"
#include "mem_root_array.h"
/* YACC and LEX Definitions */
@@ -604,6 +605,7 @@ public:
};
typedef class st_select_lex_unit SELECT_LEX_UNIT;
+typedef Bounds_checked_array<Item*> Ref_ptr_array;
/*
SELECT_LEX - store information of parsed SELECT statment
@@ -666,8 +668,9 @@ public:
SQL_I_List<ORDER> order_list; /* ORDER clause */
SQL_I_List<ORDER> *gorder_list;
Item *select_limit, *offset_limit; /* LIMIT clause parameters */
- // Arrays of pointers to top elements of all_fields list
- Item **ref_pointer_array;
+
+ /// Array of pointers to top elements of all_fields list
+ Ref_ptr_array ref_pointer_array;
/*
number of items in select_list and HAVING clause used to get number
@@ -677,7 +680,7 @@ public:
uint select_n_having_items;
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
uint between_count; /* number of between predicates in where/having/on */
- uint max_equal_elems; /* maximal number of elements in multiple equalities */
+ uint max_equal_elems; /* maximal number of elements in multiple equalities */
/*
Number of fields used in select list or where clause of current select
and all inner subselects.
=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc 2011-06-10 16:57:01 +0000
+++ b/sql/sql_load.cc 2011-06-23 10:08:08 +0000
@@ -268,15 +268,18 @@ int mysql_load(THD *thd,sql_exchange *ex
Let us also prepare SET clause, altough it is probably empty
in this case.
*/
- if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
- setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
+ setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
DBUG_RETURN(TRUE);
}
else
{ // Part field list
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
- if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
- setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
+ if (setup_fields(thd, Ref_ptr_array(),
+ fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
+ setup_fields(thd, Ref_ptr_array(),
+ set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
check_that_all_fields_are_given_values(thd, table, table_list))
DBUG_RETURN(TRUE);
/*
@@ -295,7 +298,7 @@ int mysql_load(THD *thd,sql_exchange *ex
}
}
/* Fix the expressions in SET clause */
- if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
DBUG_RETURN(TRUE);
}
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2011-06-21 07:57:31 +0000
+++ b/sql/sql_parse.cc 2011-06-23 10:08:08 +0000
@@ -3151,7 +3151,7 @@ end_with_restore_list:
if (!thd->is_fatal_error &&
(del_result= new multi_delete(aux_tables, lex->table_count)))
{
- res= mysql_select(thd, &select_lex->ref_pointer_array,
+ res= mysql_select(thd,
select_lex->get_table_list(),
select_lex->with_wild,
select_lex->item_list,
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2011-06-10 16:57:01 +0000
+++ b/sql/sql_prepare.cc 2011-06-23 10:08:08 +0000
@@ -1294,7 +1294,7 @@ static bool mysql_test_insert(Prepared_s
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto error;
}
- if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0))
goto error;
}
}
@@ -1373,7 +1373,8 @@ static int mysql_test_update(Prepared_st
table_list->register_want_access(want_privilege);
#endif
thd->lex->select_lex.no_wrap_view_item= TRUE;
- res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0);
+ res= setup_fields(thd, Ref_ptr_array(),
+ select->item_list, MARK_COLUMNS_READ, 0, 0);
thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res)
goto error;
@@ -1384,7 +1385,8 @@ static int mysql_test_update(Prepared_st
(SELECT_ACL & ~table_list->table->grant.privilege);
table_list->register_want_access(SELECT_ACL);
#endif
- if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
goto error;
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(0);
@@ -1530,7 +1532,8 @@ static bool mysql_test_do_fields(Prepare
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL))
DBUG_RETURN(TRUE);
- DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0));
+ DBUG_RETURN(setup_fields(thd, Ref_ptr_array(),
+ *values, MARK_COLUMNS_NONE, 0, 0));
}
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2011-06-10 16:57:01 +0000
+++ b/sql/sql_select.cc 2011-06-23 10:08:08 +0000
@@ -203,7 +203,7 @@ static int remove_dup_with_hash_index(TH
static bool cmp_buffer_with_ref(THD *thd, TABLE *table, TABLE_REF *tab_ref);
static bool setup_new_fields(THD *thd, List<Item> &fields,
List<Item> &all_fields, ORDER *new_order);
-static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
+static ORDER *create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
ORDER *order, List<Item> &fields,
List<Item> &all_fields,
bool *all_order_by_fields_used);
@@ -213,12 +213,12 @@ static void calc_group_buffer(JOIN *join
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
static bool alloc_group_fields(JOIN *join,ORDER *group);
// Create list for using with tempory table
-static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+static bool change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &new_list1,
List<Item> &new_list2,
uint elements, List<Item> &items);
// Create list for using with tempory table
-static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+static bool change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &new_list1,
List<Item> &new_list2,
uint elements, List<Item> &items);
@@ -384,7 +384,7 @@ bool handle_select(THD *thd, LEX *lex, s
every PS/SP execution new, we will not need reset this flag if
setup_tables_done_option changed for next rexecution
*/
- res= mysql_select(thd, &select_lex->ref_pointer_array,
+ res= mysql_select(thd,
select_lex->table_list.first,
select_lex->with_wild, select_lex->item_list,
select_lex->where,
@@ -460,7 +460,7 @@ bool handle_select(THD *thd, LEX *lex, s
bool
fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
- Item **ref_pointer_array, ORDER *group_list)
+ Ref_ptr_array ref_pointer_array, ORDER *group_list)
{
Item_outer_ref *ref;
@@ -477,7 +477,7 @@ fix_inner_refs(THD *thd, List<Item> &all
existing one. The change will lead to less operations for copying fields,
smaller temporary tables and less data passed through filesort.
*/
- if (ref_pointer_array && !ref->found_in_select_list)
+ if (!ref_pointer_array.is_empty() && !ref->found_in_select_list)
{
int el= all_fields.elements;
ref_pointer_array[el]= item;
@@ -487,7 +487,7 @@ fix_inner_refs(THD *thd, List<Item> &all
If it's needed reset each Item_ref item that refers this field with
a new reference taken from ref_pointer_array.
*/
- item_ref= ref_pointer_array + el;
+ item_ref= &ref_pointer_array[el];
}
if (ref->in_sum_func)
@@ -546,7 +546,7 @@ fix_inner_refs(THD *thd, List<Item> &all
/**
Function to setup clauses without sum functions.
*/
-inline int setup_without_group(THD *thd, Item **ref_pointer_array,
+inline int setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
TABLE_LIST *tables,
TABLE_LIST *leaves,
List<Item> &fields,
@@ -600,8 +600,7 @@ inline int setup_without_group(THD *thd,
0 on success
*/
int
-JOIN::prepare(Item ***rref_pointer_array,
- TABLE_LIST *tables_init,
+JOIN::prepare(TABLE_LIST *tables_init,
uint wild_num, Item *conds_init, uint og_num,
ORDER *order_init, ORDER *group_init,
Item *having_init,
@@ -647,18 +646,31 @@ JOIN::prepare(Item ***rref_pointer_array
table_ptr= table_ptr->next_leaf)
tables++;
- if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
- select_lex->setup_ref_array(thd, og_num) ||
- setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
- &all_fields, 1) ||
- setup_without_group(thd, (*rref_pointer_array), tables_list,
+ /*
+ Item and Item_field CTORs will both increment some counters
+ in current_select, based on the current parsing context.
+ We are not parsing anymore: any new Items created now are due to
+ query rewriting, so stop incrementing counters.
+ */
+ DBUG_ASSERT(select_lex->parsing_place == NO_MATTER);
+ select_lex->parsing_place= NO_MATTER;
+
+ if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num))
+ DBUG_RETURN(-1);
+ if (select_lex->setup_ref_array(thd, og_num))
+ DBUG_RETURN(-1);
+
+ ref_ptrs= ref_ptr_array_slice(0);
+
+ if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
+ &all_fields, 1))
+ DBUG_RETURN(-1);
+ if (setup_without_group(thd, ref_ptrs, tables_list,
select_lex->leaf_tables, fields_list,
all_fields, &conds, order, group_list,
&hidden_group_fields))
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(-1);
- ref_pointer_array= *rref_pointer_array;
-
if (having)
{
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
@@ -712,15 +724,15 @@ JOIN::prepare(Item ***rref_pointer_array
real_order= TRUE;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
- item->split_sum_func(thd, ref_pointer_array, all_fields);
+ item->split_sum_func(thd, ref_ptrs, all_fields);
}
if (!real_order)
order= NULL;
}
if (having && having->with_sum_func)
- having->split_sum_func2(thd, ref_pointer_array, all_fields,
- &having, TRUE);
+ having->split_sum_func2(thd, ref_ptrs,
+ all_fields, &having, TRUE);
if (select_lex->inner_sum_func_list)
{
Item_sum *end=select_lex->inner_sum_func_list;
@@ -728,13 +740,13 @@ JOIN::prepare(Item ***rref_pointer_array
do
{
item_sum= item_sum->next;
- item_sum->split_sum_func2(thd, ref_pointer_array,
+ item_sum->split_sum_func2(thd, ref_ptrs,
all_fields, item_sum->ref_by, FALSE);
} while (item_sum != end);
}
if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array,
+ fix_inner_refs(thd, all_fields, select_lex, ref_ptrs,
group_list))
DBUG_RETURN(-1);
@@ -753,9 +765,9 @@ JOIN::prepare(Item ***rref_pointer_array
{
Item_field *field= new Item_field(thd, *(Item_field**)ord->item);
int el= all_fields.elements;
- ref_pointer_array[el]= field;
+ ref_ptrs[el]= field;
all_fields.push_front(field);
- ord->item= ref_pointer_array + el;
+ ord->item= &ref_ptrs[el];
}
}
}
@@ -824,7 +836,6 @@ JOIN::prepare(Item ***rref_pointer_array
/* Init join struct */
count_field_types(select_lex, &tmp_table_param, all_fields, 0);
- ref_pointer_array_size= all_fields.elements*sizeof(Item*);
this->group= group_list != 0;
unit= unit_arg;
@@ -2247,7 +2258,7 @@ JOIN::optimize()
if (order)
skip_sort_order= test_if_skip_sort_order(tab, order, m_select_limit, 1,
&tab->table->keys_in_use_for_order_by);
- if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
+ if ((group_list=create_distinct_group(thd, ref_ptrs,
order, fields_list, all_fields,
&all_order_fields_used)))
{
@@ -2750,7 +2761,7 @@ void JOIN::reset()
filesort_free_buffers(exec_tmp_table2,0);
}
clear_sj_tmp_tables(this);
- if (items0)
+ if (!items0.is_empty())
set_items_ref_array(items0);
if (join_tab_save)
@@ -3032,9 +3043,9 @@ JOIN::exec()
/* Change sum_fields reference to calculated fields in tmp_table */
if (curr_join != this)
curr_join->all_fields= *curr_all_fields;
- if (!items1)
+ if (items1.is_empty())
{
- items1= items0 + all_fields.elements;
+ items1= ref_ptr_array_slice(2);
if (sort_and_group || curr_tmp_table->group ||
tmp_table_param.precomputed_group_by)
{
@@ -3197,9 +3208,9 @@ JOIN::exec()
curr_join->join_tab[0].table= 0; // Table is freed
// No sum funcs anymore
- if (!items2)
+ if (items2.is_empty())
{
- items2= items1 + all_fields.elements;
+ items2= ref_ptr_array_slice(3);
if (change_to_use_tmp_fields(thd, items2,
tmp_fields_list2, tmp_all_fields2,
fields_list.elements, tmp_all_fields1))
@@ -3252,11 +3263,11 @@ JOIN::exec()
{
DBUG_VOID_RETURN;
}
- if (!items3)
+ if (items3.is_empty())
{
- if (!items0)
+ if (items0.is_empty())
init_items_ref_array();
- items3= ref_pointer_array + (all_fields.elements*4);
+ items3= ref_ptr_array_slice(4);
setup_copy_fields(thd, &curr_join->tmp_table_param,
items3, tmp_fields_list3, tmp_all_fields3,
curr_fields_list->elements, *curr_all_fields);
@@ -3486,7 +3497,7 @@ JOIN::exec()
We also need to do this when we have temp table(s).
Otherwise we would not be able to print the query correctly.
*/
- if (items0 && (thd->lex->describe & DESCRIBE_EXTENDED) &&
+ if (!items0.is_empty() && (thd->lex->describe & DESCRIBE_EXTENDED) &&
(select_lex->linkage == DERIVED_TABLE_TYPE ||
exec_tmp_table1 || exec_tmp_table2))
set_items_ref_array(items0);
@@ -3568,7 +3579,6 @@ void JOIN::cleanup_item_list(List<Item>
An entry point to single-unit select (a select without UNION).
@param thd thread handler
- @param rref_pointer_array a reference to ref_pointer_array of
the top-level select_lex for this query
@param tables list of all tables used in this query.
The tables have been pre-opened.
@@ -3609,7 +3619,7 @@ void JOIN::cleanup_item_list(List<Item>
*/
bool
-mysql_select(THD *thd, Item ***rref_pointer_array,
+mysql_select(THD *thd,
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
Item *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulonglong select_options,
@@ -3649,7 +3659,7 @@ mysql_select(THD *thd, Item ***rref_poin
}
else
{
- err= join->prepare(rref_pointer_array, tables, wild_num,
+ err= join->prepare(tables, wild_num,
conds, og_num, order, group, having, proc_param,
select_lex, unit);
if (err)
@@ -3667,7 +3677,7 @@ mysql_select(THD *thd, Item ***rref_poin
DBUG_RETURN(TRUE); /* purecov: inspected */
THD_STAGE_INFO(thd, stage_init);
thd->used_tables=0; // Updated by setup_fields
- err= join->prepare(rref_pointer_array, tables, wild_num,
+ err= join->prepare(tables, wild_num,
conds, og_num, order, group, having, proc_param,
select_lex, unit);
if (err)
@@ -21129,7 +21139,7 @@ cp_buffer_from_ref(THD *thd, TABLE *tabl
*/
static bool
-find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
ORDER *order, List<Item> &fields, List<Item> &all_fields,
bool is_group_field)
{
@@ -21153,7 +21163,7 @@ find_order_in_list(THD *thd, Item **ref_
order_item->full_name(), thd->where);
return TRUE;
}
- order->item= ref_pointer_array + count - 1;
+ order->item= &ref_pointer_array[count - 1];
order->in_field_list= 1;
order->counter= count;
order->counter_used= 1;
@@ -21214,7 +21224,7 @@ find_order_in_list(THD *thd, Item **ref_
'shadowed' a table field with the same name, the table field will be
chosen over the derived field.
*/
- order->item= ref_pointer_array + counter;
+ order->item= &ref_pointer_array[counter];
order->in_field_list=1;
return FALSE;
}
@@ -21272,7 +21282,7 @@ find_order_in_list(THD *thd, Item **ref_
uint el= all_fields.elements;
all_fields.push_front(order_item); /* Add new field to field list. */
ref_pointer_array[el]= order_item;
- order->item= ref_pointer_array + el;
+ order->item= &ref_pointer_array[el];
return FALSE;
}
@@ -21284,7 +21294,7 @@ find_order_in_list(THD *thd, Item **ref_
the field list.
*/
-int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order)
{
thd->where="order clause";
@@ -21325,7 +21335,7 @@ int setup_order(THD *thd, Item **ref_poi
*/
int
-setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields)
{
@@ -21456,13 +21466,14 @@ setup_new_fields(THD *thd, List<Item> &f
*/
ORDER *
-create_distinct_group(THD *thd, Item **ref_pointer_array,
+create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
ORDER *order_list, List<Item> &fields,
List<Item> &all_fields,
bool *all_order_by_fields_used)
{
List_iterator<Item> li(fields);
- Item *item, **orig_ref_pointer_array= ref_pointer_array;
+ Item *item;
+ Ref_ptr_array orig_ref_pointer_array= ref_pointer_array;
ORDER *order,*group,**prev;
*all_order_by_fields_used= 1;
@@ -21516,7 +21527,7 @@ create_distinct_group(THD *thd, Item **r
int el= all_fields.elements;
orig_ref_pointer_array[el]= new_item;
all_fields.push_front(new_item);
- ord->item= orig_ref_pointer_array + el;
+ ord->item= &orig_ref_pointer_array[el];
}
else
{
@@ -21525,14 +21536,14 @@ create_distinct_group(THD *thd, Item **r
simple indexing of ref_pointer_array (order in the array and in the
list are same)
*/
- ord->item= ref_pointer_array;
+ ord->item= &ref_pointer_array[0];
}
ord->direction= ORDER::ORDER_ASC;
*prev=ord;
prev= &ord->next;
}
next_item:
- ref_pointer_array++;
+ ref_pointer_array.pop_front();
}
*prev=0;
return group;
@@ -21847,7 +21858,7 @@ int test_if_item_cache_changed(List<Cach
bool
setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
- Item **ref_pointer_array,
+ Ref_ptr_array ref_pointer_array,
List<Item> &res_selected_fields, List<Item> &res_all_fields,
uint elements, List<Item> &all_fields)
{
@@ -22128,7 +22139,7 @@ bool JOIN::make_sum_func_list(List<Item>
*/
static bool
-change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &res_selected_fields,
List<Item> &res_all_fields,
uint elements, List<Item> &all_fields)
@@ -22219,7 +22230,7 @@ change_to_use_tmp_fields(THD *thd, Item
*/
static bool
-change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &res_selected_fields,
List<Item> &res_all_fields, uint elements,
List<Item> &all_fields)
@@ -22594,15 +22605,20 @@ bool JOIN::rollup_init()
*/
tmp_table_param.group_parts= send_group_parts;
- if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
- sizeof(Item**) +
- sizeof(List<Item>) +
- ref_pointer_array_size)
- * send_group_parts )))
- return 1;
-
- rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
- rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
+ Item_null_result **null_items=
+ static_cast<Item_null_result**>(thd->alloc(sizeof(Item*)*send_group_parts));
+
+ rollup.null_items= Item_null_array(null_items, send_group_parts);
+ rollup.ref_pointer_arrays=
+ static_cast<Ref_ptr_array*>
+ (thd->alloc((sizeof(Ref_ptr_array) +
+ all_fields.elements * sizeof(Item*)) * send_group_parts));
+ rollup.fields=
+ static_cast<List<Item>*>(thd->alloc(sizeof(List<Item>) * send_group_parts));
+
+ if (!null_items || !rollup.ref_pointer_arrays || !rollup.fields)
+ return true;
+
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
/*
@@ -22614,7 +22630,7 @@ bool JOIN::rollup_init()
rollup.null_items[i]= new (thd->mem_root) Item_null_result();
List<Item> *rollup_fields= &rollup.fields[i];
rollup_fields->empty();
- rollup.ref_pointer_arrays[i]= ref_array;
+ rollup.ref_pointer_arrays[i]= Ref_ptr_array(ref_array, all_fields.elements);
ref_array+= all_fields.elements;
}
for (i= 0 ; i < send_group_parts; i++)
@@ -22760,11 +22776,11 @@ bool JOIN::rollup_make_fields(List<Item>
bool real_fields= 0;
Item *item;
List_iterator<Item> new_it(rollup.fields[pos]);
- Item **ref_array_start= rollup.ref_pointer_arrays[pos];
+ Ref_ptr_array ref_array_start= rollup.ref_pointer_arrays[pos];
ORDER *start_group;
/* Point to first hidden field */
- Item **ref_array= ref_array_start + fields_arg.elements-1;
+ uint ref_array_ix= fields_arg.elements-1;
/* Remember where the sum functions ends for the previous level */
sum_funcs_end[pos+1]= *func;
@@ -22781,7 +22797,7 @@ bool JOIN::rollup_make_fields(List<Item>
if (item == first_field)
{
real_fields= 1; // End of hidden fields
- ref_array= ref_array_start;
+ ref_array_ix= 0;
}
if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
@@ -22825,15 +22841,15 @@ bool JOIN::rollup_make_fields(List<Item>
}
}
}
- *ref_array= item;
+ ref_array_start[ref_array_ix]= item;
if (real_fields)
{
(void) new_it++; // Point to next item
new_it.replace(item); // Replace previous
- ref_array++;
+ ref_array_ix++;
}
else
- ref_array--;
+ ref_array_ix--;
}
}
sum_funcs_end[0]= *func; // Point to last function
@@ -22865,9 +22881,7 @@ int JOIN::rollup_send_data(uint idx)
for (i= send_group_parts ; i-- > idx ; )
{
/* Get reference pointers to sum functions in place */
- memcpy((char*) ref_pointer_array,
- (char*) rollup.ref_pointer_arrays[i],
- ref_pointer_array_size);
+ copy_ref_ptr_array(ref_ptrs, rollup.ref_pointer_arrays[i]);
if ((!having || having->val_int()))
{
if (send_records < unit->select_limit_cnt && do_send_rows &&
@@ -22877,7 +22891,7 @@ int JOIN::rollup_send_data(uint idx)
}
}
/* Restore ref_pointer_array */
- set_items_ref_array(current_ref_pointer_array);
+ set_items_ref_array(current_ref_ptrs);
return 0;
}
@@ -22907,9 +22921,7 @@ int JOIN::rollup_write_data(uint idx, TA
for (i= send_group_parts ; i-- > idx ; )
{
/* Get reference pointers to sum functions in place */
- memcpy((char*) ref_pointer_array,
- (char*) rollup.ref_pointer_arrays[i],
- ref_pointer_array_size);
+ copy_ref_ptr_array(ref_ptrs, rollup.ref_pointer_arrays[i]);
if ((!having || having->val_int()))
{
int write_error;
@@ -22932,7 +22944,7 @@ int JOIN::rollup_write_data(uint idx, TA
}
}
/* Restore ref_pointer_array */
- set_items_ref_array(current_ref_pointer_array);
+ set_items_ref_array(current_ref_ptrs);
return 0;
}
@@ -23573,7 +23585,7 @@ bool mysql_explain_union(THD *thd, SELEC
{
thd->lex->current_select= first;
unit->set_limit(unit->global_parameters);
- res= mysql_select(thd, &first->ref_pointer_array,
+ res= mysql_select(thd,
first->table_list.first,
first->with_wild, first->item_list,
first->where,
=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h 2011-05-26 15:20:09 +0000
+++ b/sql/sql_select.h 2011-06-23 10:08:08 +0000
@@ -1598,12 +1598,14 @@ typedef struct st_position : public Sql_
} POSITION;
+typedef Bounds_checked_array<Item_null_result*> Item_null_array;
+
typedef struct st_rollup
{
enum State { STATE_NONE, STATE_INITED, STATE_READY };
State state;
- Item_null_result **null_items;
- Item ***ref_pointer_arrays;
+ Item_null_array null_items;
+ Ref_ptr_array *ref_pointer_arrays;
List<Item> *fields;
} ROLLUP;
@@ -1879,10 +1881,19 @@ public:
FirstMatch strategy.
*/
JOIN_TAB *return_tab;
- Item **ref_pointer_array; ///<used pointer reference for this select
- // Copy of above to be used with different lists
- Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
- uint ref_pointer_array_size; ///< size of above in bytes
+
+ /*
+ Used pointer reference for this select.
+ select_lex->ref_pointer_array contains five "slices" of the same length:
+ |========|========|========|========|========|
+ ref_ptrs items0 items1 items2 items3
+ */
+ Ref_ptr_array ref_ptrs;
+ // Copy of the initial slice above, to be used with different lists
+ Ref_ptr_array items0, items1, items2, items3;
+ // Used by rollup, to restore ref_ptrs after overwriting it.
+ Ref_ptr_array current_ref_ptrs;
+
const char *zero_result_cause; ///< not 0 if exec must return zero result
bool union_part; ///< this subselect is part of union
@@ -1958,8 +1969,11 @@ public:
hidden_group_fields= 0; /*safety*/
error= 0;
return_tab= 0;
- ref_pointer_array= items0= items1= items2= items3= 0;
- ref_pointer_array_size= 0;
+ ref_ptrs.reset();
+ items0.reset();
+ items1.reset();
+ items2.reset();
+ items3.reset();
zero_result_cause= 0;
optimized= 0;
cond_equal= 0;
@@ -1979,7 +1993,7 @@ public:
first_select= sub_select;
}
- int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
+ int prepare(TABLE_LIST *tables, uint wind_num,
Item *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, SELECT_LEX *select,
SELECT_LEX_UNIT *unit);
@@ -1994,16 +2008,42 @@ public:
bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
bool before_group_by, bool recompute= FALSE);
- inline void set_items_ref_array(Item **ptr)
+ /// Initialzes a slice, see comments for ref_ptrs above.
+ Ref_ptr_array ref_ptr_array_slice(size_t slice_num)
+ {
+ size_t slice_sz= select_lex->ref_pointer_array.size() / 5U;
+ DBUG_ASSERT(select_lex->ref_pointer_array.size() % 5 == 0);
+ DBUG_ASSERT(slice_num < 5U);
+ return Ref_ptr_array(&select_lex->ref_pointer_array[slice_num * slice_sz],
+ slice_sz);
+ }
+
+ /**
+ Overwrites one slice with the contents of another slice.
+ In the normal case, dst and src have the same size().
+ However: the rollup slices may have smaller size than slice_sz.
+ */
+ void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr)
+ {
+ DBUG_ASSERT(dst_arr.size() >= src_arr.size());
+ void *dest= dst_arr.array();
+ const void *src= src_arr.array();
+ memcpy(dest, src, src_arr.size() * src_arr.element_size());
+ }
+
+ /// Overwrites 'ref_ptrs' and remembers the the source as 'current'.
+ void set_items_ref_array(Ref_ptr_array src_arr)
{
- memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
- current_ref_pointer_array= ptr;
+ copy_ref_ptr_array(ref_ptrs, src_arr);
+ current_ref_ptrs= src_arr;
}
- inline void init_items_ref_array()
+
+ /// Initializes 'items0' and remembers that it is 'current'.
+ void init_items_ref_array()
{
- items0= ref_pointer_array + all_fields.elements;
- memcpy(items0, ref_pointer_array, ref_pointer_array_size);
- current_ref_pointer_array= items0;
+ items0= ref_ptr_array_slice(1);
+ copy_ref_ptr_array(items0, ref_ptrs);
+ current_ref_ptrs= items0;
}
bool rollup_init();
@@ -2074,7 +2114,7 @@ void free_tmp_table(THD *thd, TABLE *ent
void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
List<Item> &fields, bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
- Item **ref_pointer_array,
+ Ref_ptr_array ref_pointer_array,
List<Item> &new_list1, List<Item> &new_list2,
uint elements, List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param);
@@ -2263,17 +2303,17 @@ Item *remove_eq_conds(THD *thd, Item *co
int get_quick_record(SQL_SELECT *select);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length,
SORT_FIELD *sortorder);
-int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List <Item> &all_fields, ORDER *order);
-int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
- Item **ref_pointer_array, ORDER *group_list= NULL);
+ Ref_ptr_array ref_pointer_array, ORDER *group_list= NULL);
bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option);
-bool mysql_select(THD *thd, Item ***rref_pointer_array,
+bool mysql_select(THD *thd,
TABLE_LIST *tables, uint wild_num, List<Item> &list,
Item *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulonglong select_type,
=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc 2011-05-26 15:20:09 +0000
+++ b/sql/sql_union.cc 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, 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
@@ -10,9 +10,8 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
-
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
UNION of select's
@@ -270,8 +269,7 @@ bool st_select_lex_unit::prepare(THD *th
can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
- saved_error= join->prepare(&sl->ref_pointer_array,
- sl->table_list.first,
+ saved_error= join->prepare(sl->table_list.first,
sl->with_wild,
sl->where,
(can_skip_order_by ? 0 :
@@ -419,23 +417,38 @@ bool st_select_lex_unit::prepare(THD *th
init_prepare_fake_select_lex(thd);
/* Should be done only once (the only item_list per statement) */
DBUG_ASSERT(fake_select_lex->join == 0);
- if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->variables.option_bits,
- result)))
+ if (!(fake_select_lex->join=
+ new JOIN(thd, item_list, thd->variables.option_bits, result)))
{
fake_select_lex->table_list.empty();
DBUG_RETURN(TRUE);
}
+
+ /*
+ Fake st_select_lex should have item list for correct ref_array
+ allocation.
+ */
fake_select_lex->item_list= item_list;
- thd_arg->lex->current_select= fake_select_lex;
+ thd_arg->lex->current_select= fake_select_lex;
+
+ /*
+ We need to add up n_sum_items in order to make the correct
+ allocation in setup_ref_array().
+ */
+ fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
+
saved_error= fake_select_lex->join->
- prepare(&fake_select_lex->ref_pointer_array,
- fake_select_lex->table_list.first,
- 0, 0,
- fake_select_lex->order_list.elements,
- fake_select_lex->order_list.first,
- NULL, NULL, NULL,
- fake_select_lex, this);
+ prepare(fake_select_lex->table_list.first, // tables_init
+ 0, // wild_num
+ 0, // conds_init
+ global_parameters->order_list.elements, // og_num
+ global_parameters->order_list.first, // order
+ NULL, // group_init
+ NULL, // having_init
+ NULL, // proc_param_init
+ fake_select_lex, // select_lex_arg
+ this); // unit_arg
fake_select_lex->table_list.empty();
}
}
@@ -607,18 +620,35 @@ bool st_select_lex_unit::exec()
fake_select_lex->join->no_const_tables= true;
/*
- Fake st_select_lex should have item list for correctref_array
+ Fake st_select_lex should have item list for correct ref_array
allocation.
*/
fake_select_lex->item_list= item_list;
- saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
- &result_table_list,
- 0, item_list, NULL,
- global_parameters->order_list.elements,
- global_parameters->order_list.first,
- NULL, NULL, NULL,
- fake_select_lex->options | SELECT_NO_UNLOCK,
- result, this, fake_select_lex);
+
+ /*
+ We need to add up n_sum_items in order to make the correct
+ allocation in setup_ref_array().
+ Don't add more sum_items if we have already done JOIN::prepare
+ for this (with a different join object)
+ */
+ if (fake_select_lex->ref_pointer_array.is_empty())
+ fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
+
+ saved_error=
+ mysql_select(thd,
+ &result_table_list, // tables
+ 0, // wild_num
+ item_list, // fields
+ NULL, // conds
+ global_parameters->order_list.elements, // og_num
+ global_parameters->order_list.first, // order
+ NULL, // group
+ NULL, // having
+ NULL, // proc_param
+ fake_select_lex->options | SELECT_NO_UNLOCK,
+ result, // result
+ this, // unit
+ fake_select_lex); // select_lex
}
else
{
@@ -634,7 +664,7 @@ bool st_select_lex_unit::exec()
to reset them back, we re-do all of the actions (yes it is ugly):
*/
join->init(thd, item_list, fake_select_lex->options, result);
- saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
+ saved_error= mysql_select(thd,
&result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2011-06-16 06:30:16 +0000
+++ b/sql/sql_update.cc 2011-06-23 10:08:08 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, 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
@@ -328,7 +328,8 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
table_list->register_want_access(want_privilege);
#endif
- if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
+ if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
+ fields, MARK_COLUMNS_WRITE, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */
if (table_list->view && check_fields(thd, fields))
{
@@ -359,7 +360,7 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~table->grant.privilege);
#endif
- if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0))
{
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(1); /* purecov: inspected */
@@ -1158,7 +1159,8 @@ int mysql_multi_update_prepare(THD *thd)
UPDATE_ACL, SELECT_ACL))
DBUG_RETURN(TRUE);
- if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
+ if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
+ *fields, MARK_COLUMNS_WRITE, 0, 0))
DBUG_RETURN(TRUE);
for (tl= table_list; tl ; tl= tl->next_local)
@@ -1347,7 +1349,7 @@ bool mysql_multi_update(THD *thd,
List<Item> total_list;
- res= mysql_select(thd, &select_lex->ref_pointer_array,
+ res= mysql_select(thd,
table_list, select_lex->with_wild,
total_list,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
@@ -1432,7 +1434,8 @@ int multi_update::prepare(List<Item> &no
reference tables
*/
- int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0);
+ int error= setup_fields(thd, Ref_ptr_array(),
+ *values, MARK_COLUMNS_READ, 0, 0);
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2011-06-09 18:18:22 +0000
+++ b/sql/sql_yacc.yy 2011-06-23 10:08:08 +0000
@@ -11033,7 +11033,10 @@ show:
memset(&lex->create_info, 0, sizeof(lex->create_info));
}
show_param
- {}
+ {
+ LEX *lex= Lex;
+ lex->current_select->parsing_place= NO_MATTER;
+ }
;
show_param:
@@ -11375,7 +11378,11 @@ describe:
if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
MYSQL_YYABORT;
}
- opt_describe_column {}
+ opt_describe_column
+ {
+ LEX *lex= Lex;
+ lex->current_select->parsing_place= NO_MATTER;
+ }
| describe_command opt_extended_describe
{ Lex->describe|= DESCRIBE_NORMAL; }
select
=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt 2011-05-18 08:29:46 +0000
+++ b/unittest/gunit/CMakeLists.txt 2011-06-23 10:08:08 +0000
@@ -205,6 +205,7 @@ ENDIF()
# Add tests (link them with gunit library)
SET(TESTS
bounded_queue
+ bounds_checked_array
dbug
dynarray
mdl
=== added file 'unittest/gunit/bounds_checked_array-t.cc'
--- a/unittest/gunit/bounds_checked_array-t.cc 1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/bounds_checked_array-t.cc 2011-06-23 10:08:08 +0000
@@ -0,0 +1,117 @@
+/* Copyright (c) 2011, 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+// First include (the generated) my_config.h, to get correct platform defines,
+// then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "sql_array.h"
+
+namespace {
+
+typedef Bounds_checked_array<int> Int_array;
+
+class BoundsCheckedArray : public ::testing::Test
+{
+public:
+ BoundsCheckedArray() : some_integer(0) {}
+
+ virtual void SetUp()
+ {
+ for (int ix= 0; ix < c_array_size; ++ix)
+ c_array[ix]= ix;
+ }
+
+ static const int c_array_size= 5;
+ int c_array[c_array_size];
+
+ int some_integer;
+ Int_array int_array;
+};
+
+TEST_F(BoundsCheckedArray, Empty)
+{
+ EXPECT_EQ(sizeof(int), int_array.element_size());
+ EXPECT_EQ(0U, int_array.size());
+ EXPECT_TRUE(int_array.is_empty());
+ int *pi= NULL;
+ EXPECT_EQ(pi, int_array.array());
+}
+
+#if !defined(DBUG_OFF)
+
+// Google Test recommends DeathTest suffix for classes used in death tests.
+typedef BoundsCheckedArray BoundsCheckedArrayDeathTest;
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckRead)
+{
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ int_array= Int_array(c_array, 2);
+ EXPECT_DEATH_IF_SUPPORTED(some_integer= int_array[5],
+ ".*Assertion .*n < m_size.*");
+}
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckAssign)
+{
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ int_array= Int_array(c_array, 2);
+ EXPECT_DEATH_IF_SUPPORTED(int_array[5]= some_integer,
+ ".*Assertion .*n < m_size.*");
+}
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckPopFront)
+{
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ int_array= Int_array(c_array, 1);
+ int_array.pop_front();
+ EXPECT_DEATH_IF_SUPPORTED(int_array.pop_front(),
+ ".*Assertion .*m_size > 0.*");
+}
+
+#endif // !defined(DBUG_OFF)
+
+TEST_F(BoundsCheckedArray, Indexing)
+{
+ int_array= Int_array(c_array, c_array_size);
+ EXPECT_EQ(0, int_array[0]);
+ int_array[0]= 42;
+ EXPECT_EQ(42, int_array[0]);
+}
+
+
+TEST_F(BoundsCheckedArray, Reset)
+{
+ int_array= Int_array(c_array, c_array_size);
+ EXPECT_EQ(c_array, int_array.array());
+ EXPECT_FALSE(int_array.is_empty());
+ int_array.reset();
+ int *pi= NULL;
+ EXPECT_EQ(pi, int_array.array());
+ EXPECT_TRUE(int_array.is_empty());
+}
+
+
+TEST_F(BoundsCheckedArray, PopFront)
+{
+ int_array= Int_array(c_array, c_array_size);
+ for (int ix= 0; ix < c_array_size; ++ix)
+ {
+ EXPECT_EQ(ix, int_array[0]);
+ int_array.pop_front();
+ }
+}
+
+} // namespace
Attachment: [text/bzr-bundle] bzr/tor.didriksen@oracle.com-20110623100808-qwsnq8un1w1zfg26.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk branch (tor.didriksen:3232) Bug#12590211 | Tor Didriksen | 23 Jun |