1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2003 MySQL AB
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/**
|
|
18 |
@file
|
|
19 |
||
20 |
Optimising of MIN(), MAX() and COUNT(*) queries without 'group by' clause
|
|
21 |
by replacing the aggregate expression with a constant.
|
|
22 |
||
23 |
Given a table with a compound key on columns (a,b,c), the following
|
|
24 |
types of queries are optimised (assuming the table handler supports
|
|
25 |
the required methods)
|
|
26 |
||
27 |
@verbatim
|
|
28 |
SELECT COUNT(*) FROM t1[,t2,t3,...]
|
|
29 |
SELECT MIN(b) FROM t1 WHERE a=const
|
|
30 |
SELECT MAX(c) FROM t1 WHERE a=const AND b=const
|
|
31 |
SELECT MAX(b) FROM t1 WHERE a=const AND b<const
|
|
32 |
SELECT MIN(b) FROM t1 WHERE a=const AND b>const
|
|
33 |
SELECT MIN(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
|
|
34 |
SELECT MAX(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
|
|
35 |
@endverbatim
|
|
36 |
||
37 |
Instead of '<' one can use '<=', '>', '>=' and '=' as well.
|
|
38 |
Instead of 'a=const' the condition 'a IS NULL' can be used.
|
|
39 |
||
40 |
If all selected fields are replaced then we will also remove all
|
|
41 |
involved tables and return the answer without any join. Thus, the
|
|
42 |
following query will be replaced with a row of two constants:
|
|
43 |
@verbatim
|
|
44 |
SELECT MAX(b), MIN(d) FROM t1,t2
|
|
45 |
WHERE a=const AND b<const AND d>const
|
|
46 |
@endverbatim
|
|
47 |
(assuming a index for column d of table t2 is defined)
|
|
48 |
*/
|
|
49 |
||
243.1.17
by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.) |
50 |
#include <drizzled/server_includes.h> |
51 |
#include <drizzled/sql_select.h> |
|
584.4.7
by Monty Taylor
Removed a big bank of includes from item.h. |
52 |
#include <drizzled/item/sum.h> |
53 |
#include <drizzled/item/cmpfunc.h> |
|
1
by brian
clean slate |
54 |
|
55 |
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, Field* field, |
|
482
by Brian Aker
Remove uint. |
56 |
COND *cond, uint32_t *range_fl, |
57 |
uint32_t *key_prefix_length); |
|
1
by brian
clean slate |
58 |
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field, |
482
by Brian Aker
Remove uint. |
59 |
COND *cond, uint32_t range_fl, uint32_t prefix_len); |
1
by brian
clean slate |
60 |
static int maxmin_in_range(bool max_fl, Field* field, COND *cond); |
61 |
||
62 |
||
63 |
/*
|
|
64 |
Get exact count of rows in all tables
|
|
65 |
||
66 |
SYNOPSIS
|
|
67 |
get_exact_records()
|
|
68 |
tables List of tables
|
|
69 |
||
70 |
NOTES
|
|
71 |
When this is called, we know all table handlers supports HA_HAS_RECORDS
|
|
72 |
or HA_STATS_RECORDS_IS_EXACT
|
|
73 |
||
74 |
RETURN
|
|
163
by Brian Aker
Merge Monty's code. |
75 |
UINT64_MAX Error: Could not calculate number of rows
|
1
by brian
clean slate |
76 |
# Multiplication of number of rows in all tables
|
77 |
*/
|
|
78 |
||
327.2.4
by Brian Aker
Refactoring table.h |
79 |
static uint64_t get_exact_record_count(TableList *tables) |
1
by brian
clean slate |
80 |
{
|
151
by Brian Aker
Ulonglong to uint64_t |
81 |
uint64_t count= 1; |
327.2.4
by Brian Aker
Refactoring table.h |
82 |
for (TableList *tl= tables; tl; tl= tl->next_leaf) |
1
by brian
clean slate |
83 |
{
|
84 |
ha_rows tmp= tl->table->file->records(); |
|
85 |
if ((tmp == HA_POS_ERROR)) |
|
163
by Brian Aker
Merge Monty's code. |
86 |
return UINT64_MAX; |
1
by brian
clean slate |
87 |
count*= tmp; |
88 |
}
|
|
89 |
return count; |
|
90 |
}
|
|
91 |
||
92 |
||
93 |
/**
|
|
94 |
Substitutes constants for some COUNT(), MIN() and MAX() functions.
|
|
95 |
||
96 |
@param tables list of leaves of join table tree
|
|
97 |
@param all_fields All fields to be returned
|
|
98 |
@param conds WHERE clause
|
|
99 |
||
100 |
@note
|
|
101 |
This function is only called for queries with sum functions and no
|
|
102 |
GROUP BY part.
|
|
103 |
||
104 |
@retval
|
|
105 |
0 no errors
|
|
106 |
@retval
|
|
107 |
1 if all items were resolved
|
|
108 |
@retval
|
|
109 |
HA_ERR_KEY_NOT_FOUND on impossible conditions
|
|
110 |
@retval
|
|
111 |
HA_ERR_... if a deadlock or a lock wait timeout happens, for example
|
|
112 |
*/
|
|
113 |
||
327.2.4
by Brian Aker
Refactoring table.h |
114 |
int opt_sum_query(TableList *tables, List<Item> &all_fields,COND *conds) |
1
by brian
clean slate |
115 |
{
|
116 |
List_iterator_fast<Item> it(all_fields); |
|
117 |
int const_result= 1; |
|
118 |
bool recalc_const_item= 0; |
|
151
by Brian Aker
Ulonglong to uint64_t |
119 |
uint64_t count= 1; |
163
by Brian Aker
Merge Monty's code. |
120 |
bool is_exact_count= true, maybe_exact_count= true; |
1
by brian
clean slate |
121 |
table_map removed_tables= 0, outer_tables= 0, used_tables= 0; |
122 |
table_map where_tables= 0; |
|
123 |
Item *item; |
|
124 |
int error; |
|
125 |
||
126 |
if (conds) |
|
127 |
where_tables= conds->used_tables(); |
|
128 |
||
129 |
/*
|
|
130 |
Analyze outer join dependencies, and, if possible, compute the number
|
|
131 |
of returned rows.
|
|
132 |
*/
|
|
327.2.4
by Brian Aker
Refactoring table.h |
133 |
for (TableList *tl= tables; tl; tl= tl->next_leaf) |
1
by brian
clean slate |
134 |
{
|
327.2.4
by Brian Aker
Refactoring table.h |
135 |
TableList *embedded; |
1
by brian
clean slate |
136 |
for (embedded= tl ; embedded; embedded= embedded->embedding) |
137 |
{
|
|
138 |
if (embedded->on_expr) |
|
139 |
break; |
|
140 |
}
|
|
141 |
if (embedded) |
|
142 |
/* Don't replace expression on a table that is part of an outer join */
|
|
143 |
{
|
|
144 |
outer_tables|= tl->table->map; |
|
145 |
||
146 |
/*
|
|
147 |
We can't optimise LEFT JOIN in cases where the WHERE condition
|
|
148 |
restricts the table that is used, like in:
|
|
149 |
SELECT MAX(t1.a) FROM t1 LEFT JOIN t2 join-condition
|
|
150 |
WHERE t2.field IS NULL;
|
|
151 |
*/
|
|
152 |
if (tl->table->map & where_tables) |
|
153 |
return 0; |
|
154 |
}
|
|
155 |
else
|
|
156 |
used_tables|= tl->table->map; |
|
157 |
||
158 |
/*
|
|
159 |
If the storage manager of 'tl' gives exact row count as part of
|
|
160 |
statistics (cheap), compute the total number of rows. If there are
|
|
161 |
no outer table dependencies, this count may be used as the real count.
|
|
162 |
Schema tables are filled after this function is invoked, so we can't
|
|
163 |
get row count
|
|
164 |
*/
|
|
165 |
if (!(tl->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) || |
|
166 |
tl->schema_table) |
|
167 |
{
|
|
168 |
maybe_exact_count&= test(!tl->schema_table && |
|
169 |
(tl->table->file->ha_table_flags() & |
|
170 |
HA_HAS_RECORDS)); |
|
51.1.35
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
171 |
is_exact_count= false; |
1
by brian
clean slate |
172 |
count= 1; // ensure count != 0 |
173 |
}
|
|
174 |
else
|
|
175 |
{
|
|
176 |
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); |
|
177 |
if(error) |
|
178 |
{
|
|
179 |
tl->table->file->print_error(error, MYF(ME_FATALERROR)); |
|
180 |
return error; |
|
181 |
}
|
|
182 |
count*= tl->table->file->stats.records; |
|
183 |
}
|
|
184 |
}
|
|
185 |
||
186 |
/*
|
|
187 |
Iterate through all items in the SELECT clause and replace
|
|
188 |
COUNT(), MIN() and MAX() with constants (if possible).
|
|
189 |
*/
|
|
190 |
||
191 |
while ((item= it++)) |
|
192 |
{
|
|
193 |
if (item->type() == Item::SUM_FUNC_ITEM) |
|
194 |
{
|
|
195 |
Item_sum *item_sum= (((Item_sum*) item)); |
|
196 |
switch (item_sum->sum_func()) { |
|
197 |
case Item_sum::COUNT_FUNC: |
|
198 |
/*
|
|
199 |
If the expr in COUNT(expr) can never be null we can change this
|
|
200 |
to the number of rows in the tables if this number is exact and
|
|
201 |
there are no outer joins.
|
|
202 |
*/
|
|
203 |
if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null && |
|
204 |
!outer_tables && maybe_exact_count) |
|
205 |
{
|
|
206 |
if (!is_exact_count) |
|
207 |
{
|
|
163
by Brian Aker
Merge Monty's code. |
208 |
if ((count= get_exact_record_count(tables)) == UINT64_MAX) |
1
by brian
clean slate |
209 |
{
|
210 |
/* Error from handler in counting rows. Don't optimize count() */
|
|
211 |
const_result= 0; |
|
212 |
continue; |
|
213 |
}
|
|
214 |
is_exact_count= 1; // count is now exact |
|
215 |
}
|
|
152
by Brian Aker
longlong replacement |
216 |
((Item_sum_count*) item)->make_const((int64_t) count); |
1
by brian
clean slate |
217 |
recalc_const_item= 1; |
218 |
}
|
|
219 |
else
|
|
220 |
const_result= 0; |
|
221 |
break; |
|
222 |
case Item_sum::MIN_FUNC: |
|
223 |
{
|
|
224 |
/*
|
|
225 |
If MIN(expr) is the first part of a key or if all previous
|
|
226 |
parts of the key is found in the COND, then we can use
|
|
227 |
indexes to find the key.
|
|
228 |
*/
|
|
229 |
Item *expr=item_sum->args[0]; |
|
230 |
if (expr->real_item()->type() == Item::FIELD_ITEM) |
|
231 |
{
|
|
481
by Brian Aker
Remove all of uchar. |
232 |
unsigned char key_buff[MAX_KEY_LENGTH]; |
1
by brian
clean slate |
233 |
TABLE_REF ref; |
482
by Brian Aker
Remove uint. |
234 |
uint32_t range_fl, prefix_len; |
1
by brian
clean slate |
235 |
|
236 |
ref.key_buff= key_buff; |
|
237 |
Item_field *item_field= (Item_field*) (expr->real_item()); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
238 |
Table *table= item_field->field->table; |
1
by brian
clean slate |
239 |
|
240 |
/*
|
|
241 |
Look for a partial key that can be used for optimization.
|
|
242 |
If we succeed, ref.key_length will contain the length of
|
|
243 |
this key, while prefix_len will contain the length of
|
|
244 |
the beginning of this key without field used in MIN().
|
|
245 |
Type of range for the key part for this field will be
|
|
246 |
returned in range_fl.
|
|
247 |
*/
|
|
248 |
if (table->file->inited || (outer_tables & table->map) || |
|
249 |
!find_key_for_maxmin(0, &ref, item_field->field, conds, |
|
250 |
&range_fl, &prefix_len)) |
|
251 |
{
|
|
252 |
const_result= 0; |
|
253 |
break; |
|
254 |
}
|
|
255 |
error= table->file->ha_index_init((uint) ref.key, 1); |
|
256 |
||
257 |
if (!ref.key_length) |
|
258 |
error= table->file->index_first(table->record[0]); |
|
259 |
else
|
|
260 |
{
|
|
261 |
/*
|
|
262 |
Use index to replace MIN/MAX functions with their values
|
|
263 |
according to the following rules:
|
|
264 |
|
|
265 |
1) Insert the minimum non-null values where the WHERE clause still
|
|
266 |
matches, or
|
|
267 |
2) a NULL value if there are only NULL values for key_part_k.
|
|
268 |
3) Fail, producing a row of nulls
|
|
269 |
||
270 |
Implementation: Read the smallest value using the search key. If
|
|
271 |
the interval is open, read the next value after the search
|
|
272 |
key. If read fails, and we're looking for a MIN() value for a
|
|
273 |
nullable column, test if there is an exact match for the key.
|
|
274 |
*/
|
|
275 |
if (!(range_fl & NEAR_MIN)) |
|
276 |
/*
|
|
277 |
Closed interval: Either The MIN argument is non-nullable, or
|
|
278 |
we have a >= predicate for the MIN argument.
|
|
279 |
*/
|
|
280 |
error= table->file->index_read_map(table->record[0], |
|
281 |
ref.key_buff, |
|
282 |
make_prev_keypart_map(ref.key_parts), |
|
283 |
HA_READ_KEY_OR_NEXT); |
|
284 |
else
|
|
285 |
{
|
|
286 |
/*
|
|
287 |
Open interval: There are two cases:
|
|
288 |
1) We have only MIN() and the argument column is nullable, or
|
|
289 |
2) there is a > predicate on it, nullability is irrelevant.
|
|
290 |
We need to scan the next bigger record first.
|
|
291 |
*/
|
|
292 |
error= table->file->index_read_map(table->record[0], |
|
293 |
ref.key_buff, |
|
294 |
make_prev_keypart_map(ref.key_parts), |
|
295 |
HA_READ_AFTER_KEY); |
|
296 |
/*
|
|
297 |
If the found record is outside the group formed by the search
|
|
298 |
prefix, or there is no such record at all, check if all
|
|
299 |
records in that group have NULL in the MIN argument
|
|
300 |
column. If that is the case return that NULL.
|
|
301 |
||
302 |
Check if case 1 from above holds. If it does, we should read
|
|
303 |
the skipped tuple.
|
|
304 |
*/
|
|
305 |
if (item_field->field->real_maybe_null() && |
|
306 |
ref.key_buff[prefix_len] == 1 && |
|
307 |
/*
|
|
308 |
Last keypart (i.e. the argument to MIN) is set to NULL by
|
|
309 |
find_key_for_maxmin only if all other keyparts are bound
|
|
310 |
to constants in a conjunction of equalities. Hence, we
|
|
311 |
can detect this by checking only if the last keypart is
|
|
312 |
NULL.
|
|
313 |
*/
|
|
314 |
(error == HA_ERR_KEY_NOT_FOUND || |
|
315 |
key_cmp_if_same(table, ref.key_buff, ref.key, prefix_len))) |
|
316 |
{
|
|
51.1.35
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
317 |
assert(item_field->field->real_maybe_null()); |
1
by brian
clean slate |
318 |
error= table->file->index_read_map(table->record[0], |
319 |
ref.key_buff, |
|
320 |
make_prev_keypart_map(ref.key_parts), |
|
321 |
HA_READ_KEY_EXACT); |
|
322 |
}
|
|
323 |
}
|
|
324 |
}
|
|
325 |
/* Verify that the read tuple indeed matches the search key */
|
|
326 |
if (!error && reckey_in_range(0, &ref, item_field->field, |
|
327 |
conds, range_fl, prefix_len)) |
|
328 |
error= HA_ERR_KEY_NOT_FOUND; |
|
329 |
if (table->key_read) |
|
330 |
{
|
|
331 |
table->key_read= 0; |
|
332 |
table->file->extra(HA_EXTRA_NO_KEYREAD); |
|
333 |
}
|
|
334 |
table->file->ha_index_end(); |
|
335 |
if (error) |
|
336 |
{
|
|
337 |
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) |
|
338 |
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE |
|
339 |
/* HA_ERR_LOCK_DEADLOCK or some other error */
|
|
340 |
table->file->print_error(error, MYF(0)); |
|
341 |
return(error); |
|
342 |
}
|
|
343 |
removed_tables|= table->map; |
|
344 |
}
|
|
345 |
else if (!expr->const_item() || !is_exact_count) |
|
346 |
{
|
|
347 |
/*
|
|
348 |
The optimization is not applicable in both cases:
|
|
349 |
(a) 'expr' is a non-constant expression. Then we can't
|
|
350 |
replace 'expr' by a constant.
|
|
351 |
(b) 'expr' is a costant. According to ANSI, MIN/MAX must return
|
|
352 |
NULL if the query does not return any rows. Thus, if we are not
|
|
353 |
able to determine if the query returns any rows, we can't apply
|
|
354 |
the optimization and replace MIN/MAX with a constant.
|
|
355 |
*/
|
|
356 |
const_result= 0; |
|
357 |
break; |
|
358 |
}
|
|
359 |
if (!count) |
|
360 |
{
|
|
163
by Brian Aker
Merge Monty's code. |
361 |
/* If count == 0, then we know that is_exact_count == true. */
|
1
by brian
clean slate |
362 |
((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */ |
363 |
}
|
|
364 |
else
|
|
365 |
((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */ |
|
366 |
((Item_sum_min*) item_sum)->make_const(); |
|
367 |
recalc_const_item= 1; |
|
368 |
break; |
|
369 |
}
|
|
370 |
case Item_sum::MAX_FUNC: |
|
371 |
{
|
|
372 |
/*
|
|
373 |
If MAX(expr) is the first part of a key or if all previous
|
|
374 |
parts of the key is found in the COND, then we can use
|
|
375 |
indexes to find the key.
|
|
376 |
*/
|
|
377 |
Item *expr=item_sum->args[0]; |
|
378 |
if (expr->real_item()->type() == Item::FIELD_ITEM) |
|
379 |
{
|
|
481
by Brian Aker
Remove all of uchar. |
380 |
unsigned char key_buff[MAX_KEY_LENGTH]; |
1
by brian
clean slate |
381 |
TABLE_REF ref; |
482
by Brian Aker
Remove uint. |
382 |
uint32_t range_fl, prefix_len; |
1
by brian
clean slate |
383 |
|
384 |
ref.key_buff= key_buff; |
|
385 |
Item_field *item_field= (Item_field*) (expr->real_item()); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
386 |
Table *table= item_field->field->table; |
1
by brian
clean slate |
387 |
|
388 |
/*
|
|
389 |
Look for a partial key that can be used for optimization.
|
|
390 |
If we succeed, ref.key_length will contain the length of
|
|
391 |
this key, while prefix_len will contain the length of
|
|
392 |
the beginning of this key without field used in MAX().
|
|
393 |
Type of range for the key part for this field will be
|
|
394 |
returned in range_fl.
|
|
395 |
*/
|
|
396 |
if (table->file->inited || (outer_tables & table->map) || |
|
397 |
!find_key_for_maxmin(1, &ref, item_field->field, conds, |
|
398 |
&range_fl, &prefix_len)) |
|
399 |
{
|
|
400 |
const_result= 0; |
|
401 |
break; |
|
402 |
}
|
|
403 |
error= table->file->ha_index_init((uint) ref.key, 1); |
|
404 |
||
405 |
if (!ref.key_length) |
|
406 |
error= table->file->index_last(table->record[0]); |
|
407 |
else
|
|
408 |
error= table->file->index_read_map(table->record[0], key_buff, |
|
409 |
make_prev_keypart_map(ref.key_parts), |
|
410 |
range_fl & NEAR_MAX ? |
|
411 |
HA_READ_BEFORE_KEY : |
|
412 |
HA_READ_PREFIX_LAST_OR_PREV); |
|
413 |
if (!error && reckey_in_range(1, &ref, item_field->field, |
|
414 |
conds, range_fl, prefix_len)) |
|
415 |
error= HA_ERR_KEY_NOT_FOUND; |
|
416 |
if (table->key_read) |
|
417 |
{
|
|
418 |
table->key_read=0; |
|
419 |
table->file->extra(HA_EXTRA_NO_KEYREAD); |
|
420 |
}
|
|
421 |
table->file->ha_index_end(); |
|
422 |
if (error) |
|
423 |
{
|
|
424 |
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) |
|
425 |
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE |
|
426 |
/* HA_ERR_LOCK_DEADLOCK or some other error */
|
|
427 |
table->file->print_error(error, MYF(ME_FATALERROR)); |
|
428 |
return(error); |
|
429 |
}
|
|
430 |
removed_tables|= table->map; |
|
431 |
}
|
|
432 |
else if (!expr->const_item() || !is_exact_count) |
|
433 |
{
|
|
434 |
/*
|
|
435 |
The optimization is not applicable in both cases:
|
|
436 |
(a) 'expr' is a non-constant expression. Then we can't
|
|
437 |
replace 'expr' by a constant.
|
|
438 |
(b) 'expr' is a costant. According to ANSI, MIN/MAX must return
|
|
439 |
NULL if the query does not return any rows. Thus, if we are not
|
|
440 |
able to determine if the query returns any rows, we can't apply
|
|
441 |
the optimization and replace MIN/MAX with a constant.
|
|
442 |
*/
|
|
443 |
const_result= 0; |
|
444 |
break; |
|
445 |
}
|
|
446 |
if (!count) |
|
447 |
{
|
|
163
by Brian Aker
Merge Monty's code. |
448 |
/* If count != 1, then we know that is_exact_count == true. */
|
1
by brian
clean slate |
449 |
((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */ |
450 |
}
|
|
451 |
else
|
|
452 |
((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */ |
|
453 |
((Item_sum_max*) item_sum)->make_const(); |
|
454 |
recalc_const_item= 1; |
|
455 |
break; |
|
456 |
}
|
|
457 |
default: |
|
458 |
const_result= 0; |
|
459 |
break; |
|
460 |
}
|
|
461 |
}
|
|
462 |
else if (const_result) |
|
463 |
{
|
|
464 |
if (recalc_const_item) |
|
465 |
item->update_used_tables(); |
|
466 |
if (!item->const_item()) |
|
467 |
const_result= 0; |
|
468 |
}
|
|
469 |
}
|
|
470 |
/*
|
|
471 |
If we have a where clause, we can only ignore searching in the
|
|
472 |
tables if MIN/MAX optimisation replaced all used tables
|
|
473 |
We do not use replaced values in case of:
|
|
474 |
SELECT MIN(key) FROM table_1, empty_table
|
|
475 |
removed_tables is != 0 if we have used MIN() or MAX().
|
|
476 |
*/
|
|
477 |
if (removed_tables && used_tables != removed_tables) |
|
478 |
const_result= 0; // We didn't remove all tables |
|
479 |
return const_result; |
|
480 |
}
|
|
481 |
||
482 |
||
483 |
/**
|
|
484 |
Test if the predicate compares a field with constants.
|
|
485 |
||
486 |
@param func_item Predicate item
|
|
487 |
@param[out] args Here we store the field followed by constants
|
|
488 |
@param[out] inv_order Is set to 1 if the predicate is of the form
|
|
489 |
'const op field'
|
|
490 |
||
491 |
@retval
|
|
492 |
0 func_item is a simple predicate: a field is compared with
|
|
493 |
constants
|
|
494 |
@retval
|
|
495 |
1 Otherwise
|
|
496 |
*/
|
|
497 |
||
498 |
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) |
|
499 |
{
|
|
500 |
Item *item; |
|
501 |
*inv_order= 0; |
|
502 |
switch (func_item->argument_count()) { |
|
503 |
case 0: |
|
504 |
/* MULT_EQUAL_FUNC */
|
|
505 |
{
|
|
506 |
Item_equal *item_equal= (Item_equal *) func_item; |
|
507 |
Item_equal_iterator it(*item_equal); |
|
508 |
args[0]= it++; |
|
509 |
if (it++) |
|
510 |
return 0; |
|
511 |
if (!(args[1]= item_equal->get_const())) |
|
512 |
return 0; |
|
513 |
}
|
|
514 |
break; |
|
515 |
case 1: |
|
516 |
/* field IS NULL */
|
|
517 |
item= func_item->arguments()[0]; |
|
518 |
if (item->type() != Item::FIELD_ITEM) |
|
519 |
return 0; |
|
520 |
args[0]= item; |
|
521 |
break; |
|
522 |
case 2: |
|
523 |
/* 'field op const' or 'const op field' */
|
|
524 |
item= func_item->arguments()[0]; |
|
525 |
if (item->type() == Item::FIELD_ITEM) |
|
526 |
{
|
|
527 |
args[0]= item; |
|
528 |
item= func_item->arguments()[1]; |
|
529 |
if (!item->const_item()) |
|
530 |
return 0; |
|
531 |
args[1]= item; |
|
532 |
}
|
|
533 |
else if (item->const_item()) |
|
534 |
{
|
|
535 |
args[1]= item; |
|
536 |
item= func_item->arguments()[1]; |
|
537 |
if (item->type() != Item::FIELD_ITEM) |
|
538 |
return 0; |
|
539 |
args[0]= item; |
|
540 |
*inv_order= 1; |
|
541 |
}
|
|
542 |
else
|
|
543 |
return 0; |
|
544 |
break; |
|
545 |
case 3: |
|
546 |
/* field BETWEEN const AND const */
|
|
547 |
item= func_item->arguments()[0]; |
|
548 |
if (item->type() == Item::FIELD_ITEM) |
|
549 |
{
|
|
550 |
args[0]= item; |
|
551 |
for (int i= 1 ; i <= 2; i++) |
|
552 |
{
|
|
553 |
item= func_item->arguments()[i]; |
|
554 |
if (!item->const_item()) |
|
555 |
return 0; |
|
556 |
args[i]= item; |
|
557 |
}
|
|
558 |
}
|
|
559 |
else
|
|
560 |
return 0; |
|
561 |
}
|
|
562 |
return 1; |
|
563 |
}
|
|
564 |
||
565 |
||
566 |
/**
|
|
567 |
Check whether a condition matches a key to get {MAX|MIN}(field):.
|
|
568 |
||
569 |
For the index specified by the keyinfo parameter, index that
|
|
570 |
contains field as its component (field_part), the function
|
|
571 |
checks whether the condition cond is a conjunction and all its
|
|
572 |
conjuncts referring to the columns of the same table as column
|
|
573 |
field are one of the following forms:
|
|
574 |
- f_i= const_i or const_i= f_i or f_i is null,
|
|
575 |
where f_i is part of the index
|
|
576 |
- field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field
|
|
577 |
- field between const1 and const2
|
|
578 |
||
579 |
@param[in] max_fl Set to 1 if we are optimising MAX()
|
|
580 |
@param[in,out] ref Reference to the structure we store the key
|
|
581 |
value
|
|
582 |
@param[in] keyinfo Reference to the key info
|
|
583 |
@param[in] field_part Pointer to the key part for the field
|
|
584 |
@param[in] cond WHERE condition
|
|
585 |
@param[in,out] key_part_used Map of matchings parts
|
|
586 |
@param[in,out] range_fl Says whether including key will be used
|
|
587 |
@param[out] prefix_len Length of common key part for the range
|
|
588 |
where MAX/MIN is searched for
|
|
589 |
||
590 |
@retval
|
|
591 |
0 Index can't be used.
|
|
592 |
@retval
|
|
593 |
1 We can use index to get MIN/MAX value
|
|
594 |
*/
|
|
595 |
||
596 |
static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, |
|
597 |
KEY_PART_INFO *field_part, COND *cond, |
|
482
by Brian Aker
Remove uint. |
598 |
key_part_map *key_part_used, uint32_t *range_fl, |
599 |
uint32_t *prefix_len) |
|
1
by brian
clean slate |
600 |
{
|
601 |
if (!cond) |
|
602 |
return 1; |
|
603 |
Field *field= field_part->field; |
|
604 |
if (!(cond->used_tables() & field->table->map)) |
|
605 |
{
|
|
606 |
/* Condition doesn't restrict the used table */
|
|
607 |
return 1; |
|
608 |
}
|
|
609 |
if (cond->type() == Item::COND_ITEM) |
|
610 |
{
|
|
611 |
if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC) |
|
612 |
return 0; |
|
613 |
||
614 |
/* AND */
|
|
615 |
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); |
|
616 |
Item *item; |
|
617 |
while ((item= li++)) |
|
618 |
{
|
|
619 |
if (!matching_cond(max_fl, ref, keyinfo, field_part, item, |
|
620 |
key_part_used, range_fl, prefix_len)) |
|
621 |
return 0; |
|
622 |
}
|
|
623 |
return 1; |
|
624 |
}
|
|
625 |
||
626 |
if (cond->type() != Item::FUNC_ITEM) |
|
627 |
return 0; // Not operator, can't optimize |
|
628 |
||
629 |
bool eq_type= 0; // =, <=> or IS NULL |
|
630 |
bool noeq_type= 0; // < or > |
|
631 |
bool less_fl= 0; // < or <= |
|
632 |
bool is_null= 0; |
|
633 |
bool between= 0; |
|
634 |
||
635 |
switch (((Item_func*) cond)->functype()) { |
|
636 |
case Item_func::ISNULL_FUNC: |
|
637 |
is_null= 1; /* fall through */ |
|
638 |
case Item_func::EQ_FUNC: |
|
639 |
case Item_func::EQUAL_FUNC: |
|
640 |
eq_type= 1; |
|
641 |
break; |
|
642 |
case Item_func::LT_FUNC: |
|
643 |
noeq_type= 1; /* fall through */ |
|
644 |
case Item_func::LE_FUNC: |
|
645 |
less_fl= 1; |
|
646 |
break; |
|
647 |
case Item_func::GT_FUNC: |
|
648 |
noeq_type= 1; /* fall through */ |
|
649 |
case Item_func::GE_FUNC: |
|
650 |
break; |
|
651 |
case Item_func::BETWEEN: |
|
652 |
between= 1; |
|
653 |
break; |
|
654 |
case Item_func::MULT_EQUAL_FUNC: |
|
655 |
eq_type= 1; |
|
656 |
break; |
|
657 |
default: |
|
658 |
return 0; // Can't optimize function |
|
659 |
}
|
|
660 |
||
661 |
Item *args[3]; |
|
662 |
bool inv; |
|
663 |
||
664 |
/* Test if this is a comparison of a field and constant */
|
|
665 |
if (!simple_pred((Item_func*) cond, args, &inv)) |
|
666 |
return 0; |
|
667 |
||
668 |
if (inv && !eq_type) |
|
669 |
less_fl= 1-less_fl; // Convert '<' -> '>' (etc) |
|
670 |
||
671 |
/* Check if field is part of the tested partial key */
|
|
481
by Brian Aker
Remove all of uchar. |
672 |
unsigned char *key_ptr= ref->key_buff; |
1
by brian
clean slate |
673 |
KEY_PART_INFO *part; |
674 |
for (part= keyinfo->key_part; ; key_ptr+= part++->store_length) |
|
675 |
||
676 |
{
|
|
677 |
if (part > field_part) |
|
678 |
return 0; // Field is beyond the tested parts |
|
679 |
if (part->field->eq(((Item_field*) args[0])->field)) |
|
680 |
break; // Found a part of the key for the field |
|
681 |
}
|
|
682 |
||
683 |
bool is_field_part= part == field_part; |
|
684 |
if (!(is_field_part || eq_type)) |
|
685 |
return 0; |
|
686 |
||
687 |
key_part_map org_key_part_used= *key_part_used; |
|
688 |
if (eq_type || between || max_fl == less_fl) |
|
689 |
{
|
|
482
by Brian Aker
Remove uint. |
690 |
uint32_t length= (key_ptr-ref->key_buff)+part->store_length; |
1
by brian
clean slate |
691 |
if (ref->key_length < length) |
692 |
{
|
|
693 |
/* Ultimately ref->key_length will contain the length of the search key */
|
|
694 |
ref->key_length= length; |
|
695 |
ref->key_parts= (part - keyinfo->key_part) + 1; |
|
696 |
}
|
|
697 |
if (!*prefix_len && part+1 == field_part) |
|
698 |
*prefix_len= length; |
|
699 |
if (is_field_part && eq_type) |
|
700 |
*prefix_len= ref->key_length; |
|
701 |
||
702 |
*key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part); |
|
703 |
}
|
|
704 |
||
705 |
if (org_key_part_used != *key_part_used || |
|
706 |
(is_field_part && |
|
707 |
(between || eq_type || max_fl == less_fl) && !cond->val_int())) |
|
708 |
{
|
|
709 |
/*
|
|
710 |
It's the first predicate for this part or a predicate of the
|
|
711 |
following form that moves upper/lower bounds for max/min values:
|
|
712 |
- field BETWEEN const AND const
|
|
713 |
- field = const
|
|
714 |
- field {<|<=} const, when searching for MAX
|
|
715 |
- field {>|>=} const, when searching for MIN
|
|
716 |
*/
|
|
717 |
||
718 |
if (is_null) |
|
719 |
{
|
|
720 |
part->field->set_null(); |
|
481
by Brian Aker
Remove all of uchar. |
721 |
*key_ptr= (unsigned char) 1; |
1
by brian
clean slate |
722 |
}
|
723 |
else
|
|
724 |
{
|
|
725 |
store_val_in_field(part->field, args[between && max_fl ? 2 : 1], |
|
726 |
CHECK_FIELD_IGNORE); |
|
727 |
if (part->null_bit) |
|
481
by Brian Aker
Remove all of uchar. |
728 |
*key_ptr++= (unsigned char) test(part->field->is_null()); |
1
by brian
clean slate |
729 |
part->field->get_key_image(key_ptr, part->length, Field::itRAW); |
730 |
}
|
|
731 |
if (is_field_part) |
|
732 |
{
|
|
733 |
if (between || eq_type) |
|
734 |
*range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE); |
|
735 |
else
|
|
736 |
{
|
|
737 |
*range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE); |
|
738 |
if (noeq_type) |
|
739 |
*range_fl|= (max_fl ? NEAR_MAX : NEAR_MIN); |
|
740 |
else
|
|
741 |
*range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN); |
|
742 |
}
|
|
743 |
}
|
|
744 |
}
|
|
745 |
else if (eq_type) |
|
746 |
{
|
|
747 |
if ((!is_null && !cond->val_int()) || |
|
748 |
(is_null && !test(part->field->is_null()))) |
|
749 |
return 0; // Impossible test |
|
750 |
}
|
|
751 |
else if (is_field_part) |
|
752 |
*range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE); |
|
753 |
return 1; |
|
754 |
}
|
|
755 |
||
756 |
||
757 |
/**
|
|
758 |
Check whether we can get value for {max|min}(field) by using a key.
|
|
759 |
||
760 |
If where-condition is not a conjunction of 0 or more conjuct the
|
|
761 |
function returns false, otherwise it checks whether there is an
|
|
762 |
index including field as its k-th component/part such that:
|
|
763 |
||
764 |
-# for each previous component f_i there is one and only one conjunct
|
|
765 |
of the form: f_i= const_i or const_i= f_i or f_i is null
|
|
766 |
-# references to field occur only in conjucts of the form:
|
|
767 |
field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field or
|
|
768 |
field BETWEEN const1 AND const2
|
|
769 |
-# all references to the columns from the same table as column field
|
|
770 |
occur only in conjucts mentioned above.
|
|
771 |
-# each of k first components the index is not partial, i.e. is not
|
|
772 |
defined on a fixed length proper prefix of the field.
|
|
773 |
||
774 |
If such an index exists the function through the ref parameter
|
|
775 |
returns the key value to find max/min for the field using the index,
|
|
776 |
the length of first (k-1) components of the key and flags saying
|
|
777 |
how to apply the key for the search max/min value.
|
|
778 |
(if we have a condition field = const, prefix_len contains the length
|
|
779 |
of the whole search key)
|
|
780 |
||
781 |
@param[in] max_fl 0 for MIN(field) / 1 for MAX(field)
|
|
782 |
@param[in,out] ref Reference to the structure we store the key value
|
|
783 |
@param[in] field Field used inside MIN() / MAX()
|
|
784 |
@param[in] cond WHERE condition
|
|
785 |
@param[out] range_fl Bit flags for how to search if key is ok
|
|
786 |
@param[out] prefix_len Length of prefix for the search range
|
|
787 |
||
788 |
@note
|
|
789 |
This function may set table->key_read to 1, which must be reset after
|
|
790 |
index is used! (This can only happen when function returns 1)
|
|
791 |
||
792 |
@retval
|
|
793 |
0 Index can not be used to optimize MIN(field)/MAX(field)
|
|
794 |
@retval
|
|
795 |
1 Can use key to optimize MIN()/MAX().
|
|
796 |
In this case ref, range_fl and prefix_len are updated
|
|
797 |
*/
|
|
798 |
||
799 |
||
800 |
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, |
|
801 |
Field* field, COND *cond, |
|
482
by Brian Aker
Remove uint. |
802 |
uint32_t *range_fl, uint32_t *prefix_len) |
1
by brian
clean slate |
803 |
{
|
804 |
if (!(field->flags & PART_KEY_FLAG)) |
|
805 |
return 0; // Not key field |
|
806 |
||
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
807 |
Table *table= field->table; |
482
by Brian Aker
Remove uint. |
808 |
uint32_t idx= 0; |
1
by brian
clean slate |
809 |
|
810 |
KEY *keyinfo,*keyinfo_end; |
|
811 |
for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ; |
|
812 |
keyinfo != keyinfo_end; |
|
813 |
keyinfo++,idx++) |
|
814 |
{
|
|
815 |
KEY_PART_INFO *part,*part_end; |
|
816 |
key_part_map key_part_to_use= 0; |
|
817 |
/*
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
818 |
Perform a check if index is not disabled by ALTER Table
|
1
by brian
clean slate |
819 |
or IGNORE INDEX.
|
820 |
*/
|
|
821 |
if (!table->keys_in_use_for_query.is_set(idx)) |
|
822 |
continue; |
|
482
by Brian Aker
Remove uint. |
823 |
uint32_t jdx= 0; |
1
by brian
clean slate |
824 |
*prefix_len= 0; |
825 |
for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ; |
|
826 |
part != part_end ; |
|
827 |
part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1) |
|
828 |
{
|
|
829 |
if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER)) |
|
830 |
return 0; |
|
831 |
||
832 |
/* Check whether the index component is partial */
|
|
833 |
Field *part_field= table->field[part->fieldnr-1]; |
|
834 |
if ((part_field->flags & BLOB_FLAG) || |
|
835 |
part->length < part_field->key_length()) |
|
836 |
break; |
|
837 |
||
838 |
if (field->eq(part->field)) |
|
839 |
{
|
|
840 |
ref->key= idx; |
|
841 |
ref->key_length= 0; |
|
842 |
ref->key_parts= 0; |
|
843 |
key_part_map key_part_used= 0; |
|
844 |
*range_fl= NO_MIN_RANGE | NO_MAX_RANGE; |
|
845 |
if (matching_cond(max_fl, ref, keyinfo, part, cond, |
|
846 |
&key_part_used, range_fl, prefix_len) && |
|
847 |
!(key_part_to_use & ~key_part_used)) |
|
848 |
{
|
|
849 |
if (!max_fl && key_part_used == key_part_to_use && part->null_bit) |
|
850 |
{
|
|
851 |
/*
|
|
852 |
The query is on this form:
|
|
853 |
||
854 |
SELECT MIN(key_part_k)
|
|
855 |
FROM t1
|
|
856 |
WHERE key_part_1 = const and ... and key_part_k-1 = const
|
|
857 |
||
858 |
If key_part_k is nullable, we want to find the first matching row
|
|
859 |
where key_part_k is not null. The key buffer is now {const, ...,
|
|
860 |
NULL}. This will be passed to the handler along with a flag
|
|
861 |
indicating open interval. If a tuple is read that does not match
|
|
862 |
these search criteria, an attempt will be made to read an exact
|
|
863 |
match for the key buffer.
|
|
864 |
*/
|
|
865 |
/* Set the first byte of key_part_k to 1, that means NULL */
|
|
866 |
ref->key_buff[ref->key_length]= 1; |
|
867 |
ref->key_length+= part->store_length; |
|
868 |
ref->key_parts++; |
|
51.1.35
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
869 |
assert(ref->key_parts == jdx+1); |
1
by brian
clean slate |
870 |
*range_fl&= ~NO_MIN_RANGE; |
871 |
*range_fl|= NEAR_MIN; // Open interval |
|
872 |
}
|
|
873 |
/*
|
|
874 |
The following test is false when the key in the key tree is
|
|
875 |
converted (for example to upper case)
|
|
876 |
*/
|
|
877 |
if (field->part_of_key.is_set(idx)) |
|
878 |
{
|
|
879 |
table->key_read= 1; |
|
880 |
table->file->extra(HA_EXTRA_KEYREAD); |
|
881 |
}
|
|
882 |
return 1; |
|
883 |
}
|
|
884 |
}
|
|
885 |
}
|
|
886 |
}
|
|
887 |
return 0; |
|
888 |
}
|
|
889 |
||
890 |
||
891 |
/**
|
|
892 |
Check whether found key is in range specified by conditions.
|
|
893 |
||
894 |
@param[in] max_fl 0 for MIN(field) / 1 for MAX(field)
|
|
895 |
@param[in] ref Reference to the key value and info
|
|
896 |
@param[in] field Field used the MIN/MAX expression
|
|
897 |
@param[in] cond WHERE condition
|
|
898 |
@param[in] range_fl Says whether there is a condition to to be checked
|
|
899 |
@param[in] prefix_len Length of the constant part of the key
|
|
900 |
||
901 |
@retval
|
|
902 |
0 ok
|
|
903 |
@retval
|
|
904 |
1 WHERE was not true for the found row
|
|
905 |
*/
|
|
906 |
||
907 |
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field, |
|
482
by Brian Aker
Remove uint. |
908 |
COND *cond, uint32_t range_fl, uint32_t prefix_len) |
1
by brian
clean slate |
909 |
{
|
910 |
if (key_cmp_if_same(field->table, ref->key_buff, ref->key, prefix_len)) |
|
911 |
return 1; |
|
912 |
if (!cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE))) |
|
913 |
return 0; |
|
914 |
return maxmin_in_range(max_fl, field, cond); |
|
915 |
}
|
|
916 |
||
917 |
||
918 |
/**
|
|
919 |
Check whether {MAX|MIN}(field) is in range specified by conditions.
|
|
920 |
||
921 |
@param[in] max_fl 0 for MIN(field) / 1 for MAX(field)
|
|
922 |
@param[in] field Field used the MIN/MAX expression
|
|
923 |
@param[in] cond WHERE condition
|
|
924 |
||
925 |
@retval
|
|
926 |
0 ok
|
|
927 |
@retval
|
|
928 |
1 WHERE was not true for the found row
|
|
929 |
*/
|
|
930 |
||
931 |
static int maxmin_in_range(bool max_fl, Field* field, COND *cond) |
|
932 |
{
|
|
933 |
/* If AND/OR condition */
|
|
934 |
if (cond->type() == Item::COND_ITEM) |
|
935 |
{
|
|
936 |
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); |
|
937 |
Item *item; |
|
938 |
while ((item= li++)) |
|
939 |
{
|
|
940 |
if (maxmin_in_range(max_fl, field, item)) |
|
941 |
return 1; |
|
942 |
}
|
|
943 |
return 0; |
|
944 |
}
|
|
945 |
||
946 |
if (cond->used_tables() != field->table->map) |
|
947 |
return 0; |
|
948 |
bool less_fl= 0; |
|
949 |
switch (((Item_func*) cond)->functype()) { |
|
950 |
case Item_func::BETWEEN: |
|
951 |
return cond->val_int() == 0; // Return 1 if WHERE is false |
|
952 |
case Item_func::LT_FUNC: |
|
953 |
case Item_func::LE_FUNC: |
|
954 |
less_fl= 1; |
|
955 |
case Item_func::GT_FUNC: |
|
956 |
case Item_func::GE_FUNC: |
|
957 |
{
|
|
958 |
Item *item= ((Item_func*) cond)->arguments()[1]; |
|
959 |
/* In case of 'const op item' we have to swap the operator */
|
|
960 |
if (!item->const_item()) |
|
961 |
less_fl= 1-less_fl; |
|
962 |
/*
|
|
963 |
We only have to check the expression if we are using an expression like
|
|
964 |
SELECT MAX(b) FROM t1 WHERE a=const AND b>const
|
|
965 |
not for
|
|
966 |
SELECT MAX(b) FROM t1 WHERE a=const AND b<const
|
|
967 |
*/
|
|
968 |
if (max_fl != less_fl) |
|
969 |
return cond->val_int() == 0; // Return 1 if WHERE is false |
|
970 |
return 0; |
|
971 |
}
|
|
972 |
case Item_func::EQ_FUNC: |
|
973 |
case Item_func::EQUAL_FUNC: |
|
974 |
break; |
|
975 |
default: // Keep compiler happy |
|
51.1.35
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
976 |
assert(1); // Impossible |
1
by brian
clean slate |
977 |
break; |
978 |
}
|
|
979 |
return 0; |
|
980 |
}
|
|
981 |