1 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA */
15 
16 #ifndef FILESORT_INCLUDED
17 #define FILESORT_INCLUDED
18 
19 #include "my_base.h"                            /* ha_rows */
20 #include "sql_alloc.h"
21 #include "filesort_utils.h"
22 
23 class SQL_SELECT;
24 class THD;
25 struct TABLE;
26 class Filesort_tracker;
27 struct SORT_FIELD;
28 struct SORT_FIELD_ATTR;
29 typedef struct st_order ORDER;
30 class JOIN;
31 class Addon_fields;
32 class Sort_keys;
33 
34 
35 /**
36   Sorting related info.
37   To be extended by another WL to include complete filesort implementation.
38 */
39 class Filesort: public Sql_alloc
40 {
41 public:
42   /** List of expressions to order the table by */
43   ORDER *order;
44   /** Number of records to return */
45   ha_rows limit;
46   /** ORDER BY list with some precalculated info for filesort */
47   SORT_FIELD *sortorder;
48   /** select to use for getting records */
49   SQL_SELECT *select;
50   /** TRUE <=> free select on destruction */
51   bool own_select;
52   /** true means we are using Priority Queue for order by with limit. */
53   bool using_pq;
54 
55   /*
56     TRUE means sort operation must produce table rowids.
57     FALSE means that it halso has an option of producing {sort_key,
58     addon_fields} pairs.
59   */
60   bool sort_positions;
61 
62   Filesort_tracker *tracker;
63   Sort_keys *sort_keys;
64 
Filesort(ORDER * order_arg,ha_rows limit_arg,bool sort_positions_arg,SQL_SELECT * select_arg)65   Filesort(ORDER *order_arg, ha_rows limit_arg, bool sort_positions_arg,
66            SQL_SELECT *select_arg):
67     order(order_arg),
68     limit(limit_arg),
69     sortorder(NULL),
70     select(select_arg),
71     own_select(false),
72     using_pq(false),
73     sort_positions(sort_positions_arg),
74     sort_keys(NULL)
75   {
76     DBUG_ASSERT(order);
77   };
78 
~Filesort()79   ~Filesort() { cleanup(); }
80   /* Prepare ORDER BY list for sorting. */
81   Sort_keys* make_sortorder(THD *thd, JOIN *join, table_map first_table_bit);
82 
83 private:
84   void cleanup();
85 };
86 
87 
88 class SORT_INFO
89 {
90   /// Buffer for sorting keys.
91   Filesort_buffer filesort_buffer;
92 
93 public:
SORT_INFO()94   SORT_INFO()
95     :addon_fields(NULL), record_pointers(0),
96      sort_keys(NULL),
97      sorted_result_in_fsbuf(FALSE)
98   {
99     buffpek.str= 0;
100     my_b_clear(&io_cache);
101   }
102 
103   ~SORT_INFO();
104 
free_data()105   void free_data()
106   {
107     close_cached_file(&io_cache);
108     free_addon_buff();
109     my_free(record_pointers);
110     my_free(buffpek.str);
111     my_free(addon_fields);
112     free_sort_buffer();
113   }
114 
reset()115   void reset()
116   {
117     free_data();
118     record_pointers= 0;
119     buffpek.str= 0;
120     addon_fields= 0;
121     sorted_result_in_fsbuf= false;
122   }
123 
124   void free_addon_buff();
125 
126   IO_CACHE  io_cache;           /* If sorted through filesort */
127   LEX_STRING buffpek;           /* Buffer for buffpek structures */
128   Addon_fields *addon_fields;   /* Addon field descriptors */
129   uchar     *record_pointers;    /* If sorted in memory */
130   Sort_keys *sort_keys;         /* Sort key descriptors*/
131 
132   /**
133     If the entire result of filesort fits in memory, we skip the merge phase.
134     We may leave the result in filesort_buffer
135     (indicated by sorted_result_in_fsbuf), or we may strip away
136     the sort keys, and copy the sorted result into a new buffer.
137     @see save_index()
138    */
139   bool      sorted_result_in_fsbuf;
140 
141   /*
142     How many rows in final result.
143     Also how many rows in record_pointers, if used
144   */
145   ha_rows   return_rows;
146   ha_rows   examined_rows;	/* How many rows read */
147   ha_rows   found_rows;         /* How many rows was accepted */
148 
149   /** Sort filesort_buffer */
sort_buffer(Sort_param * param,uint count)150   void sort_buffer(Sort_param *param, uint count)
151   { filesort_buffer.sort_buffer(param, count); }
152 
get_sort_keys()153   uchar **get_sort_keys()
154   { return filesort_buffer.get_sort_keys(); }
155 
get_sorted_record(uint ix)156   uchar *get_sorted_record(uint ix)
157   { return filesort_buffer.get_sorted_record(ix); }
158 
alloc_sort_buffer(uint num_records,uint record_length)159   uchar *alloc_sort_buffer(uint num_records, uint record_length)
160   { return filesort_buffer.alloc_sort_buffer(num_records, record_length); }
161 
free_sort_buffer()162   void free_sort_buffer()
163   { filesort_buffer.free_sort_buffer(); }
164 
isfull()165   bool isfull() const
166   { return filesort_buffer.isfull(); }
init_record_pointers()167   void init_record_pointers()
168   { filesort_buffer.init_record_pointers(); }
init_next_record_pointer()169   void init_next_record_pointer()
170   { filesort_buffer.init_next_record_pointer(); }
get_next_record_pointer()171   uchar *get_next_record_pointer()
172   { return filesort_buffer.get_next_record_pointer(); }
adjust_next_record_pointer(uint val)173   void adjust_next_record_pointer(uint val)
174   { filesort_buffer.adjust_next_record_pointer(val); }
175 
get_raw_buf()176   Bounds_checked_array<uchar> get_raw_buf()
177   { return filesort_buffer.get_raw_buf(); }
178 
sort_buffer_size()179   size_t sort_buffer_size() const
180   { return filesort_buffer.sort_buffer_size(); }
181 
is_allocated()182   bool is_allocated() const
183   { return filesort_buffer.is_allocated(); }
set_sort_length(uint val)184   void set_sort_length(uint val)
185   { filesort_buffer.set_sort_length(val); }
get_sort_length()186   uint get_sort_length() const
187   { return filesort_buffer.get_sort_length(); }
188 
has_filesort_result_in_memory()189   bool has_filesort_result_in_memory() const
190   {
191     return record_pointers || sorted_result_in_fsbuf;
192   }
193 
194   /// Are we using "addon fields"?
using_addon_fields()195   bool using_addon_fields() const
196   {
197     return addon_fields != NULL;
198   }
199 
200   /// Are we using "packed addon fields"?
201   bool using_packed_addons();
202 
203   /**
204     Copies (unpacks) values appended to sorted fields from a buffer back to
205     their regular positions specified by the Field::ptr pointers.
206     @param buff            Buffer which to unpack the value from
207   */
208   template<bool Packed_addon_fields>
209   inline void unpack_addon_fields(uchar *buff);
210 
211   bool using_packed_sortkeys();
212 
213   friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
214                              Filesort_tracker* tracker, JOIN *join,
215                              table_map first_table_bit);
216 };
217 
218 SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
219                     Filesort_tracker* tracker, JOIN *join=NULL,
220                     table_map first_table_bit=0);
221 
222 bool filesort_use_addons(TABLE *table, uint sortlength,
223                          uint *length, uint *fields, uint *null_fields,
224                          uint *m_packable_length);
225 
226 void change_double_for_sort(double nr,uchar *to);
227 void store_length(uchar *to, uint length, uint pack_length);
228 void
229 reverse_key(uchar *to, const SORT_FIELD_ATTR *sort_field);
230 
231 #endif /* FILESORT_INCLUDED */
232