Commit 2656709a authored by Sergey Petrunya's avatar Sergey Petrunya

Merge

parents 34d901c0 24c2fea6
...@@ -950,8 +950,7 @@ typedef long long my_ptrdiff_t; ...@@ -950,8 +950,7 @@ typedef long long my_ptrdiff_t;
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) #define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */ /* Size to make adressable obj. */
#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t))) #define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A), sizeof(double)))
/* Offset of field f in structure t */
#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f) #define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f)
#define ADD_TO_PTR(ptr,size,type) (type) ((uchar*) (ptr)+size) #define ADD_TO_PTR(ptr,size,type) (type) ((uchar*) (ptr)+size)
#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((uchar*) (A) - (uchar*) (B)) #define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((uchar*) (A) - (uchar*) (B))
......
...@@ -290,10 +290,6 @@ print "time for select_one_attribute ($count:$rows): " . ...@@ -290,10 +290,6 @@ print "time for select_one_attribute ($count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
###
### TODO...
###
; ;
#### ####
......
...@@ -1916,10 +1916,10 @@ void Item_field::reset_field(Field *f) ...@@ -1916,10 +1916,10 @@ void Item_field::reset_field(Field *f)
} }
bool Item_field::check_column_usage_processor(uchar *arg) bool Item_field::enumerate_field_refs_processor(uchar *arg)
{ {
Field_enumerator *fe= (Field_enumerator*)arg; Field_enumerator *fe= (Field_enumerator*)arg;
fe->see_field(field); fe->visit_field(field);
return FALSE; return FALSE;
} }
......
...@@ -734,7 +734,7 @@ public: ...@@ -734,7 +734,7 @@ public:
/* /*
Bitmap of tables used by item Bitmap of tables used by item
(note: if you need to check dependencies on individual columns, check out (note: if you need to check dependencies on individual columns, check out
check_column_usage_processor) class Field_enumerator)
*/ */
virtual table_map used_tables() const { return (table_map) 0L; } virtual table_map used_tables() const { return (table_map) 0L; }
/* /*
...@@ -892,7 +892,7 @@ public: ...@@ -892,7 +892,7 @@ public:
virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
virtual bool is_expensive_processor(uchar *arg) { return 0; } virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; } virtual bool register_field_in_read_map(uchar *arg) { return 0; }
virtual bool check_column_usage_processor(uchar *arg) { return 0; } virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; } virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
/* /*
Check if a partition function is allowed Check if a partition function is allowed
...@@ -1018,14 +1018,29 @@ public: ...@@ -1018,14 +1018,29 @@ public:
}; };
/* Data for Item::check_column_usage_processor */ /*
Class to be used to enumerate all field references in an item tree.
Suggested usage:
class My_enumerator : public Field_enumerator
{
virtual void visit_field() { ... your actions ...}
}
My_enumerator enumerator;
item->walk(Item::enumerate_field_refs_processor, ...,(uchar*)&enumerator);
This is similar to Visitor pattern.
*/
class Field_enumerator class Field_enumerator
{ {
public: public:
virtual void see_field(Field *field)= 0; virtual void visit_field(Field *field)= 0;
virtual ~Field_enumerator() {}; /* Shut up compiler warning */ virtual ~Field_enumerator() {}; /* purecov: inspected */
}; };
class sp_head; class sp_head;
...@@ -1491,7 +1506,7 @@ public: ...@@ -1491,7 +1506,7 @@ public:
bool find_item_in_field_list_processor(uchar *arg); bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg); bool register_field_in_read_map(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_column_usage_processor(uchar *arg); bool enumerate_field_refs_processor(uchar *arg);
void cleanup(); void cleanup();
bool result_as_longlong() bool result_as_longlong()
{ {
......
...@@ -5168,33 +5168,7 @@ void Item_equal::merge(Item_equal *item) ...@@ -5168,33 +5168,7 @@ void Item_equal::merge(Item_equal *item)
void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
{ {
bool swap; exchange_sort<Item_field>(&fields, cmp, arg);
List_iterator<Item_field> it(fields);
do
{
Item_field *item1= it++;
Item_field **ref1= it.ref();
Item_field *item2;
swap= FALSE;
while ((item2= it++))
{
Item_field **ref2= it.ref();
if (cmp(item1, item2, arg) < 0)
{
Item_field *item= *ref1;
*ref1= *ref2;
*ref2= item;
swap= TRUE;
}
else
{
item1= item2;
ref1= ref2;
}
}
it.rewind();
} while (swap);
} }
......
...@@ -215,13 +215,13 @@ err: ...@@ -215,13 +215,13 @@ err:
} }
bool Item_subselect::check_column_usage_processor(uchar *arg) bool Item_subselect::enumerate_field_refs_processor(uchar *arg)
{ {
List_iterator<Item> it(refers_to); List_iterator<Item> it(refers_to);
Item *item; Item *item;
while ((item= it++)) while ((item= it++))
{ {
if (item->walk(&Item::check_column_usage_processor,FALSE, arg)) if (item->walk(&Item::enumerate_field_refs_processor, FALSE, arg))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
......
...@@ -135,7 +135,7 @@ public: ...@@ -135,7 +135,7 @@ public:
enum_parsing_place place() { return parsing_place; } enum_parsing_place place() { return parsing_place; }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
bool mark_as_eliminated_processor(uchar *arg); bool mark_as_eliminated_processor(uchar *arg);
bool check_column_usage_processor(uchar *arg); bool enumerate_field_refs_processor(uchar *arg);
/** /**
Get the SELECT_LEX structure associated with this Item. Get the SELECT_LEX structure associated with this Item.
......
This diff is collapsed.
...@@ -442,6 +442,43 @@ public: ...@@ -442,6 +442,43 @@ public:
}; };
/*
Exchange sort algorithm for List<T>.
*/
template <class T>
inline void exchange_sort(List<T> *list_to_sort,
int (*sort_func)(T *a, T *b, void *arg), void *arg)
{
bool swap;
List_iterator<T> it(*list_to_sort);
do
{
T *item1= it++;
T **ref1= it.ref();
T *item2;
swap= FALSE;
while ((item2= it++))
{
T **ref2= it.ref();
if (sort_func(item1, item2, arg) < 0)
{
T *item= *ref1;
*ref1= *ref2;
*ref2= item;
swap= TRUE;
}
else
{
item1= item2;
ref1= ref2;
}
}
it.rewind();
} while (swap);
}
/* /*
A simple intrusive list which automaticly removes element from list A simple intrusive list which automaticly removes element from list
on delete (for THD element) on delete (for THD element)
......
...@@ -2991,22 +2991,33 @@ typedef struct key_field_t { ...@@ -2991,22 +2991,33 @@ typedef struct key_field_t {
elements that would correspond to "$LEFT_PART OR $RIGHT_PART". elements that would correspond to "$LEFT_PART OR $RIGHT_PART".
The rules for combining elements are as follows: The rules for combining elements are as follows:
(keyfieldA1 AND keyfieldA2 AND ...) OR (keyfieldB1 AND keyfieldB2 AND ...)= (keyfieldA1 AND keyfieldA2 AND ...) OR (keyfieldB1 AND keyfieldB2 AND ...)=
AND_ij (keyfieldA_i OR keyfieldB_j)
= AND_ij (keyfieldA_i OR keyfieldB_j)
We discard all (keyfieldA_i OR keyfieldB_j) that refer to different We discard all (keyfieldA_i OR keyfieldB_j) that refer to different
fields. For those referring to the same field, the logic is as follows: fields. For those referring to the same field, the logic is as follows:
t.keycol= t.keycol=expr1 OR t.keycol=expr2 -> (since expr1 and expr2 are different
we can't produce a single equality,
so produce nothing)
t.keycol=expr1 OR t.keycol=expr1 -> t.keycol=expr1
t.keycol=expr1 OR t.keycol IS NULL -> t.keycol=expr1, and also set
KEY_OPTIMIZE_REF_OR_NULL flag
To be able to do 'ref_or_null' we merge a comparison of a column The last one is for ref_or_null access. We have handling for this special
and 'column IS NULL' to one test. This is useful for sub select queries because it's needed for evaluating IN subqueries that are internally
that are internally transformed to something like:. transformed into
@code @code
SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL EXISTS(SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL)
@endcode @endcode
See add_key_fields() for discussion of what is and_level.
KEY_FIELD::null_rejecting is processed as follows: @n KEY_FIELD::null_rejecting is processed as follows: @n
result has null_rejecting=true if it is set for both ORed references. result has null_rejecting=true if it is set for both ORed references.
for example: for example:
...@@ -3346,6 +3357,26 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level, ...@@ -3346,6 +3357,26 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
} }
} }
/*
In this and other functions, and_level is a number that is ever-growing
and is different for the contents of every AND or OR clause. For example,
when processing clause
(a AND b AND c) OR (x AND y)
we'll have
* KEY_FIELD elements for (a AND b AND c) are assigned and_level=1
* KEY_FIELD elements for (x AND y) are assigned and_level=2
* OR operation is performed, and whatever elements are left after it are
assigned and_level=3.
The primary reason for having and_level attribute is the OR operation which
uses and_level to mark KEY_FIELDs that should get into the result of the OR
operation
*/
static void static void
add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
COND *cond, table_map usable_tables, COND *cond, table_map usable_tables,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment