Commit 51564575 authored by Sergey Petrunya's avatar Sergey Petrunya

Address review feedback

- One iterator class
- Switch back from state automaton into two-nested-iterators approach..
parent 22d5323f
...@@ -462,7 +462,6 @@ SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b ...@@ -462,7 +462,6 @@ SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
LEFT JOIN LEFT JOIN
(t1,t2) (t1,t2)
ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b; ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b;
SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
FROM (t3,t4) FROM (t3,t4)
LEFT JOIN LEFT JOIN
......
...@@ -586,6 +586,7 @@ if (`select @@join_cache_level=6`) ...@@ -586,6 +586,7 @@ if (`select @@join_cache_level=6`)
--echo # Not anymore: --echo # Not anymore:
--echo # The following query gives wrong result due to Bug#49129 --echo # The following query gives wrong result due to Bug#49129
} }
select sin(0);
select * from t0 where t0.a in select * from t0 where t0.a in
(select t1.a from t1, t2 where t2.a=t0.a and t1.b=t2.b); (select t1.a from t1, t2 where t2.a=t0.a and t1.b=t2.b);
......
This diff is collapsed.
...@@ -48,6 +48,37 @@ ...@@ -48,6 +48,37 @@
#include "sql_lifo_buffer.h" #include "sql_lifo_buffer.h"
class DsMrr_impl;
/**
Iterator over (record, range_id) pairs that match given key value.
We may need to scan multiple (key_val, range_id) pairs with the same
key value. A key value may have multiple matching records, so we'll need to
produce a cross-product of sets of matching records and range_id-s.
*/
class Key_value_records_iterator
{
/* Scan parameters */
DsMrr_impl *dsmrr;
Lifo_buffer_iterator identical_key_it;
uchar *last_identical_key_ptr;
bool get_next_row;
public:
/*
*/
bool init(DsMrr_impl *dsmrr);
/*
Get next (key_val, range_id) pair.
*/
int get_next();
void close();
};
/* /*
DS-MRR implementation for one table. Create/use one object of this class for DS-MRR implementation for one table. Create/use one object of this class for
each ha_{myisam/innobase/etc} object. That object will be further referred to each ha_{myisam/innobase/etc} object. That object will be further referred to
...@@ -197,17 +228,6 @@ private: ...@@ -197,17 +228,6 @@ private:
/** Index scaning and key buffer-related members **/ /** Index scaning and key buffer-related members **/
enum enum_index_scan_state {
REFILL_KEY_BUFFER,
GET_NEXT_RANGE,
GET_NEXT_RECORD,
GET_NEXT_IDENTICAL_KEY,
SCAN_FINISHED
};
enum enum_index_scan_state index_scan_state;
/* TRUE <=> We can get at most one index tuple for a lookup key */ /* TRUE <=> We can get at most one index tuple for a lookup key */
bool index_ranges_unique; bool index_ranges_unique;
...@@ -220,25 +240,26 @@ private: ...@@ -220,25 +240,26 @@ private:
buffers. buffers.
*/ */
Forward_lifo_buffer forward_key_buf; Forward_lifo_buffer forward_key_buf;
Forward_iterator forward_key_it;
Backward_lifo_buffer backward_key_buf; Backward_lifo_buffer backward_key_buf;
Backward_iterator backward_key_it;
/* Buffer to store (key, range_id) pairs */ /* Buffer to store (key, range_id) pairs */
Lifo_buffer *key_buffer; Lifo_buffer *key_buffer;
/* key_buffer.read() reads */ /* Index scan state */
uchar *cur_index_tuple; bool scanning_key_val_iter;
/* if in_index_range==TRUE: range_id of the range we're enumerating */
char *cur_range_info;
/* /*
TRUE <=> we've got index tuples/rowids for all keys (need this flag because TRUE <=> we've got index tuples/rowids for all keys (need this flag because
we may have a situation where we've read everything from the key buffer but we may have a situation where we've read everything from the key buffer but
haven't finished with getting index tuples for the last key) haven't finished with getting index tuples for the last key)
*/ */
//bool key_eof; bool index_scan_eof;
Key_value_records_iterator kv_it;
/* key_buffer.read() reads to here */
uchar *cur_index_tuple;
/* if in_index_range==TRUE: range_id of the range we're enumerating */
char *cur_range_info;
/* Initially FALSE, becomes TRUE when we've set key_tuple_xxx members */ /* Initially FALSE, becomes TRUE when we've set key_tuple_xxx members */
bool know_key_tuple_params; bool know_key_tuple_params;
...@@ -255,28 +276,6 @@ private: ...@@ -255,28 +276,6 @@ private:
/* = key_size_in_keybuf [ + sizeof(range_assoc_info) ] */ /* = key_size_in_keybuf [ + sizeof(range_assoc_info) ] */
uint key_buff_elem_size; uint key_buff_elem_size;
/*
TRUE <=> we're doing key-ordered index scan and right now several
subsequent key values are the same as the one we've already retrieved and
returned index tuple for.
*/
//bool in_identical_keys_range;
/* range_id of the first of the identical keys */
char *first_identical_range_info;
/* Pointer to the last of the identical key values */
uchar *last_identical_key_ptr;
/*
key_buffer iterator for walking the identical key range (we need to
enumerate the set of (identical_key, range_id) pairs multiple times,
and do that by walking from current buffer read position until we get
last_identical_key_ptr.
*/
Lifo_buffer::Iterator *identical_key_it;
/** rnd_pos() scan and rowid buffer-related members **/ /** rnd_pos() scan and rowid buffer-related members **/
/* /*
...@@ -289,11 +288,6 @@ private: ...@@ -289,11 +288,6 @@ private:
uchar *rowid; uchar *rowid;
uchar *rowids_range_id; uchar *rowids_range_id;
/*
not-NULL: we're traversing a group of (rowid, range_id) pairs with
identical rowid values, and this is the pointer to the last one.
NULL: we're not in the group of indentical rowids.
*/
uchar *last_identical_rowid; uchar *last_identical_rowid;
bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */ bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
...@@ -315,10 +309,9 @@ private: ...@@ -315,10 +309,9 @@ private:
void setup_buffer_sizes(key_range *sample_key); void setup_buffer_sizes(key_range *sample_key);
void reallocate_buffer_space(); void reallocate_buffer_space();
void read_out_identical_ranges();
static range_seq_t key_buf_seq_init(void *init_param, uint n_ranges, uint flags); static range_seq_t key_buf_seq_init(void *init_param, uint n_ranges, uint flags);
static uint key_buf_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range); static uint key_buf_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range);
friend class Key_value_records_iterator;
}; };
/** /**
......
...@@ -112,40 +112,17 @@ public: ...@@ -112,40 +112,17 @@ public:
virtual void reset() = 0; virtual void reset() = 0;
virtual uchar *end_of_space() = 0; virtual uchar *end_of_space() = 0;
protected: protected:
bool have_data(size_t bytes)
{
return (used_size() >= bytes);
}
virtual bool have_space_for(size_t bytes) = 0; virtual bool have_space_for(size_t bytes) = 0;
virtual size_t used_size() = 0; virtual size_t used_size() = 0;
/* To be used only by iterator class: */
virtual uchar *get_pos()= 0;
virtual bool read(uchar **position)= 0;
friend class Lifo_buffer_iterator;
public: public:
virtual void remove_unused_space(uchar **unused_start, uchar **unused_end)=0; virtual void remove_unused_space(uchar **unused_start, uchar **unused_end)=0;
virtual uchar *used_area() = 0; virtual uchar *used_area() = 0;
/** Iterator to walk over contents of the buffer without reading it. */
class Iterator
{
public:
virtual void init(Lifo_buffer *buf) = 0;
/*
Read the next value. The calling convention is the same as buf->read()
has.
@retval FALSE - ok
@retval TRUE - EOF, reached the end of the buffer
*/
virtual bool read_next()= 0;
virtual ~Iterator() {}
protected:
Lifo_buffer *buf;
virtual uchar *get_next(size_t nbytes)=0;
};
virtual ~Lifo_buffer() {}; virtual ~Lifo_buffer() {};
friend class Forward_iterator;
friend class Backward_iterator;
}; };
...@@ -196,19 +173,24 @@ public: ...@@ -196,19 +173,24 @@ public:
memcpy(pos, data, bytes); memcpy(pos, data, bytes);
pos += bytes; pos += bytes;
} }
uchar *read_bytes(size_t bytes) bool have_data(uchar *position, size_t bytes)
{ {
DBUG_ASSERT(have_data(bytes)); return ((position - start) >= (ptrdiff_t)bytes);
pos= pos - bytes;
return pos;
} }
bool read() uchar *read_bytes(uchar **position, size_t bytes)
{
DBUG_ASSERT(have_data(*position, bytes));
*position= (*position) - bytes;
return *position;
}
bool read() { return read(&pos); }
bool read(uchar **position)
{ {
if (!have_data(size1 + (read_ptr2 ? size2 : 0))) if (!have_data(*position, size1 + (read_ptr2 ? size2 : 0)))
return TRUE; return TRUE;
if (read_ptr2) if (read_ptr2)
*read_ptr2= read_bytes(size2); *read_ptr2= read_bytes(position, size2);
*read_ptr1= read_bytes(size1); *read_ptr1= read_bytes(position, size1);
return FALSE; return FALSE;
} }
void remove_unused_space(uchar **unused_start, uchar **unused_end) void remove_unused_space(uchar **unused_start, uchar **unused_end)
...@@ -231,58 +213,11 @@ public: ...@@ -231,58 +213,11 @@ public:
} }
/* Return pointer to start of the memory area that is occupied by the data */ /* Return pointer to start of the memory area that is occupied by the data */
uchar *used_area() { return start; } uchar *used_area() { return start; }
friend class Forward_iterator; friend class Lifo_buffer_iterator;
uchar *get_pos() { return pos; }
}; };
/**
Iterator for Forward_lifo_buffer
*/
class Forward_iterator : public Lifo_buffer::Iterator
{
uchar *pos;
/** Return pointer to next chunk of nbytes bytes and avance over it */
uchar *get_next(size_t nbytes)
{
if (pos - nbytes < ((Forward_lifo_buffer*)buf)->start)
return NULL;
pos -= nbytes;
return pos;
}
public:
bool read_next()
{
uchar *res;
if (buf->read_ptr2)
{
if ((res= get_next(buf->size2)))
{
*(buf->read_ptr2)= res;
*buf->read_ptr1= get_next(buf->size1);
return FALSE;
}
}
else
{
if ((res= get_next(buf->size1)))
{
*(buf->read_ptr1)= res;
return FALSE;
}
}
return TRUE; /* EOF */
}
void init(Lifo_buffer *buf_arg)
{
DBUG_ASSERT(buf_arg->type() == Lifo_buffer::FORWARD);
buf= buf_arg;
pos= ((Forward_lifo_buffer*)buf)->pos;
}
};
/** /**
Backward LIFO buffer Backward LIFO buffer
...@@ -332,18 +267,26 @@ public: ...@@ -332,18 +267,26 @@ public:
} }
bool read() bool read()
{ {
if (!have_data(size1 + (read_ptr2 ? size2 : 0))) return read(&pos);
}
bool read(uchar **position)
{
if (!have_data(*position, size1 + (read_ptr2 ? size2 : 0)))
return TRUE; return TRUE;
*read_ptr1= read_bytes(size1); *read_ptr1= read_bytes(position, size1);
if (read_ptr2) if (read_ptr2)
*read_ptr2= read_bytes(size2); *read_ptr2= read_bytes(position, size2);
return FALSE; return FALSE;
} }
uchar *read_bytes(size_t bytes) bool have_data(uchar *position, size_t bytes)
{
return ((end - position) >= (ptrdiff_t)bytes);
}
uchar *read_bytes(uchar **position, size_t bytes)
{ {
DBUG_ASSERT(have_data(bytes)); DBUG_ASSERT(have_data(*position, bytes));
uchar *ret= pos; uchar *ret= *position;
pos= pos + bytes; *position= *position + bytes;
return ret; return ret;
} }
/** /**
...@@ -363,50 +306,34 @@ public: ...@@ -363,50 +306,34 @@ public:
} }
/* Return pointer to start of the memory area that is occupied by the data */ /* Return pointer to start of the memory area that is occupied by the data */
uchar *used_area() { return pos; } uchar *used_area() { return pos; }
friend class Backward_iterator; friend class Lifo_buffer_iterator;
uchar *get_pos() { return pos; }
}; };
/**
Iterator for Backward_lifo_buffer
*/
class Backward_iterator : public Lifo_buffer::Iterator /** Iterator to walk over contents of the buffer without reading it. */
class Lifo_buffer_iterator
{ {
uchar *pos; uchar *pos;
/* Return pointer to next chunk of nbytes bytes and advance over it */ Lifo_buffer *buf;
uchar *get_next(size_t nbytes)
{
if (pos + nbytes > ((Backward_lifo_buffer*)buf)->end)
return NULL;
uchar *res= pos;
pos += nbytes;
return res;
}
public: public:
bool read_next() void init(Lifo_buffer *buf_arg)
{ {
buf= buf_arg;
pos= buf->get_pos();
}
/* /*
Always read the first component first (if the buffer is backwards, we Read the next value. The calling convention is the same as buf->read()
have written the second component first). has.
@retval FALSE - ok
@retval TRUE - EOF, reached the end of the buffer
*/ */
uchar *res; bool read()
if ((res= get_next(buf->size1)))
{
*(buf->read_ptr1)= res;
if (buf->read_ptr2)
*buf->read_ptr2= get_next(buf->size2);
return FALSE;
}
return TRUE; /* EOF */
}
void init(Lifo_buffer *buf_arg)
{ {
DBUG_ASSERT(buf_arg->type() == Lifo_buffer::BACKWARD); return buf->read(&pos);
buf= buf_arg;
pos= ((Backward_lifo_buffer*)buf)->pos;
} }
}; };
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