diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2016-09-23 14:18:29 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2016-09-23 14:21:07 +0300 |
commit | a13de89a54b5e0245cf7d67ca716131abd1fcd96 (patch) | |
tree | 5f16362eba3300982b0c47896fdc3067d26d3792 /sql/sql_window.cc | |
parent | 0f8a1a314d49adfe8e20c5e4d3e98e37b91b068e (diff) | |
download | mariadb-git-bb-10.2-mdev9736.tar.gz |
MDEV-9736: Window functions: multiple cursors to read filesort resultbb-10.2-mdev9736
Add support for having multiple IO_CACHEs with type=READ_CACHE to share
the file they are reading from.
Each IO_CACHE keeps its own in-memory buffer. When doing a read or seek
operation on the file, it notifies other IO_CACHEs that the file position
has been changed.
Make Rowid_seq_cursor use cloned IO_CACHE when reading filesort result.
Diffstat (limited to 'sql/sql_window.cc')
-rw-r--r-- | sql/sql_window.cc | 164 |
1 files changed, 109 insertions, 55 deletions
diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 4705fdce896..e49002b1db4 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -515,17 +515,6 @@ void order_window_funcs_by_window_specs(List<Item_window_func> *win_func_list) // note: make rr_from_pointers static again when not need it here anymore int rr_from_pointers(READ_RECORD *info); -/* - A temporary way to clone READ_RECORD structures until Monty provides the real - one. -*/ -bool clone_read_record(const READ_RECORD *src, READ_RECORD *dst) -{ - //DBUG_ASSERT(src->table->sort.record_pointers); - DBUG_ASSERT(src->read_record == rr_from_pointers); - memcpy(dst, src, sizeof(READ_RECORD)); - return false; -} ///////////////////////////////////////////////////////////////////////////// @@ -540,68 +529,145 @@ bool clone_read_record(const READ_RECORD *src, READ_RECORD *dst) class Rowid_seq_cursor { public: - virtual ~Rowid_seq_cursor() {} + Rowid_seq_cursor() : io_cache(NULL), ref_buffer(0) {} + virtual ~Rowid_seq_cursor() + { + if (ref_buffer) + my_free(ref_buffer); + if (io_cache) + { + end_slave_io_cache(io_cache); + my_free(io_cache); + io_cache= NULL; + } + } + +private: + /* Length of one rowid element */ + size_t ref_length; + + /* If io_cache=!NULL, use it */ + IO_CACHE *io_cache; + uchar *ref_buffer; /* Buffer for the last returned rowid */ + uint rownum; /* Number of the rowid that is about to be returned */ + bool cache_eof; /* whether we've reached EOF */ + + /* The following are used when we are reading from an array of pointers */ + uchar *cache_start; + uchar *cache_pos; + uchar *cache_end; +public: void init(READ_RECORD *info) { - cache_start= info->cache_pos; - cache_pos= info->cache_pos; - cache_end= info->cache_end; ref_length= info->ref_length; + if (info->read_record == rr_from_pointers) + { + io_cache= NULL; + cache_start= info->cache_pos; + cache_pos= info->cache_pos; + cache_end= info->cache_end; + } + else + { + //DBUG_ASSERT(info->read_record == rr_from_tempfile); + rownum= 0; + cache_eof= false; + io_cache= (IO_CACHE*)my_malloc(sizeof(IO_CACHE), MYF(0)); + init_slave_io_cache(info->io_cache, io_cache); + + ref_buffer= (uchar*)my_malloc(ref_length, MYF(0)); + } } virtual int next() { - /* Allow multiple next() calls in EOF state. */ - if (cache_pos == cache_end) - return -1; - - cache_pos+= ref_length; - DBUG_ASSERT(cache_pos <= cache_end); + if (io_cache) + { + if (cache_eof) + return 1; + if (my_b_read(io_cache,ref_buffer,ref_length)) + { + cache_eof= 1; // TODO: remove cache_eof + return -1; + } + rownum++; + return 0; + } + else + { + /* Allow multiple next() calls in EOF state. */ + if (cache_pos == cache_end) + return -1; + cache_pos+= ref_length; + DBUG_ASSERT(cache_pos <= cache_end); + } return 0; } virtual int prev() { - /* Allow multiple prev() calls when positioned at the start. */ - if (cache_pos == cache_start) - return -1; - cache_pos-= ref_length; - DBUG_ASSERT(cache_pos >= cache_start); + if (io_cache) + { + if (rownum == 0) + return -1; - return 0; + move_to(rownum - 1); + return 0; + } + else + { + /* Allow multiple prev() calls when positioned at the start. */ + if (cache_pos == cache_start) + return -1; + cache_pos-= ref_length; + DBUG_ASSERT(cache_pos >= cache_start); + return 0; + } } ha_rows get_rownum() const { - return (cache_pos - cache_start) / ref_length; + if (io_cache) + return rownum; + else + return (cache_pos - cache_start) / ref_length; } void move_to(ha_rows row_number) { - cache_pos= MY_MIN(cache_end, cache_start + row_number * ref_length); - DBUG_ASSERT(cache_pos <= cache_end); + if (io_cache) + { + seek_io_cache(io_cache, row_number * ref_length); + rownum= row_number; + next(); + } + else + { + cache_pos= MY_MIN(cache_end, cache_start + row_number * ref_length); + DBUG_ASSERT(cache_pos <= cache_end); + } } protected: - bool at_eof() { return (cache_pos == cache_end); } - - uchar *get_prev_rowid() + bool at_eof() { - if (cache_pos == cache_start) - return NULL; + if (io_cache) + { + return cache_eof; + } else - return cache_pos - ref_length; + return (cache_pos == cache_end); } - uchar *get_curr_rowid() { return cache_pos; } - -private: - uchar *cache_start; - uchar *cache_pos; - uchar *cache_end; - uint ref_length; + uchar *get_curr_rowid() + { + if (io_cache) + return ref_buffer; + else + return cache_pos; + } }; @@ -630,18 +696,6 @@ public: return table->file->ha_rnd_pos(record, curr_rowid); } - bool fetch_prev_row() - { - uchar *p; - if ((p= get_prev_rowid())) - { - int rc= table->file->ha_rnd_pos(record, p); - if (!rc) - return true; // restored ok - } - return false; // didn't restore - } - private: /* The table that is acccesed by this cursor. */ TABLE *table; |