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 |
/* compare and test functions */
|
|
18 |
||
19 |
#ifdef USE_PRAGMA_INTERFACE
|
|
20 |
#pragma interface /* gcc class implementation */ |
|
21 |
#endif
|
|
22 |
||
23 |
extern Item_result item_cmp_type(Item_result a,Item_result b); |
|
24 |
class Item_bool_func2; |
|
25 |
class Arg_comparator; |
|
26 |
||
27 |
typedef int (Arg_comparator::*arg_cmp_func)(); |
|
28 |
||
29 |
typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg); |
|
30 |
||
31 |
class Arg_comparator: public Sql_alloc |
|
32 |
{
|
|
33 |
Item **a, **b; |
|
34 |
arg_cmp_func func; |
|
35 |
Item_bool_func2 *owner; |
|
36 |
Arg_comparator *comparators; // used only for compare_row() |
|
37 |
double precision; |
|
38 |
/* Fields used in DATE/DATETIME comparison. */
|
|
39 |
THD *thd; |
|
40 |
enum_field_types a_type, b_type; // Types of a and b items |
|
41 |
Item *a_cache, *b_cache; // Cached values of a and b items |
|
42 |
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC |
|
43 |
enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, |
|
44 |
CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; |
|
151
by Brian Aker
Ulonglong to uint64_t |
45 |
uint64_t (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, |
1
by brian
clean slate |
46 |
Item *warn_item, bool *is_null); |
47 |
public: |
|
48 |
DTCollation cmp_collation; |
|
49 |
||
50 |
Arg_comparator(): thd(0), a_cache(0), b_cache(0) {}; |
|
51 |
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), |
|
52 |
a_cache(0), b_cache(0) {}; |
|
53 |
||
54 |
int set_compare_func(Item_bool_func2 *owner, Item_result type); |
|
55 |
inline int set_compare_func(Item_bool_func2 *owner_arg) |
|
56 |
{
|
|
57 |
return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(), |
|
58 |
(*b)->result_type())); |
|
59 |
}
|
|
60 |
int set_cmp_func(Item_bool_func2 *owner_arg, |
|
61 |
Item **a1, Item **a2, |
|
62 |
Item_result type); |
|
63 |
||
64 |
inline int set_cmp_func(Item_bool_func2 *owner_arg, |
|
65 |
Item **a1, Item **a2) |
|
66 |
{
|
|
67 |
return set_cmp_func(owner_arg, a1, a2, |
|
68 |
item_cmp_type((*a1)->result_type(), |
|
69 |
(*a2)->result_type())); |
|
70 |
}
|
|
71 |
inline int compare() { return (this->*func)(); } |
|
72 |
||
73 |
int compare_string(); // compare args[0] & args[1] |
|
74 |
int compare_binary_string(); // compare args[0] & args[1] |
|
75 |
int compare_real(); // compare args[0] & args[1] |
|
76 |
int compare_decimal(); // compare args[0] & args[1] |
|
77 |
int compare_int_signed(); // compare args[0] & args[1] |
|
78 |
int compare_int_signed_unsigned(); |
|
79 |
int compare_int_unsigned_signed(); |
|
80 |
int compare_int_unsigned(); |
|
81 |
int compare_row(); // compare args[0] & args[1] |
|
82 |
int compare_e_string(); // compare args[0] & args[1] |
|
83 |
int compare_e_binary_string(); // compare args[0] & args[1] |
|
84 |
int compare_e_real(); // compare args[0] & args[1] |
|
85 |
int compare_e_decimal(); // compare args[0] & args[1] |
|
86 |
int compare_e_int(); // compare args[0] & args[1] |
|
87 |
int compare_e_int_diff_signedness(); |
|
88 |
int compare_e_row(); // compare args[0] & args[1] |
|
89 |
int compare_real_fixed(); |
|
90 |
int compare_e_real_fixed(); |
|
91 |
int compare_datetime(); // compare args[0] & args[1] as DATETIMEs |
|
92 |
||
93 |
static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, |
|
151
by Brian Aker
Ulonglong to uint64_t |
94 |
uint64_t *const_val_arg); |
1
by brian
clean slate |
95 |
|
96 |
void set_datetime_cmp_func(Item **a1, Item **b1); |
|
97 |
static arg_cmp_func comparator_matrix [5][2]; |
|
98 |
||
99 |
friend class Item_func; |
|
100 |
};
|
|
101 |
||
102 |
class Item_bool_func :public Item_int_func |
|
103 |
{
|
|
104 |
public: |
|
105 |
Item_bool_func() :Item_int_func() {} |
|
106 |
Item_bool_func(Item *a) :Item_int_func(a) {} |
|
107 |
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {} |
|
108 |
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} |
|
109 |
bool is_bool_func() { return 1; } |
|
110 |
void fix_length_and_dec() { decimals=0; max_length=1; } |
|
111 |
uint decimal_precision() const { return 1; } |
|
112 |
};
|
|
113 |
||
114 |
||
115 |
/**
|
|
116 |
Abstract Item class, to represent <code>X IS [NOT] (TRUE | FALSE)</code>
|
|
117 |
boolean predicates.
|
|
118 |
*/
|
|
119 |
||
120 |
class Item_func_truth : public Item_bool_func |
|
121 |
{
|
|
122 |
public: |
|
123 |
virtual bool val_bool(); |
|
152
by Brian Aker
longlong replacement |
124 |
virtual int64_t val_int(); |
1
by brian
clean slate |
125 |
virtual void fix_length_and_dec(); |
126 |
virtual void print(String *str, enum_query_type query_type); |
|
127 |
||
128 |
protected: |
|
129 |
Item_func_truth(Item *a, bool a_value, bool a_affirmative) |
|
130 |
: Item_bool_func(a), value(a_value), affirmative(a_affirmative) |
|
131 |
{}
|
|
132 |
||
133 |
~Item_func_truth() |
|
134 |
{}
|
|
135 |
private: |
|
136 |
/**
|
|
137 |
True for <code>X IS [NOT] TRUE</code>,
|
|
138 |
false for <code>X IS [NOT] FALSE</code> predicates.
|
|
139 |
*/
|
|
140 |
const bool value; |
|
141 |
/**
|
|
142 |
True for <code>X IS Y</code>, false for <code>X IS NOT Y</code> predicates.
|
|
143 |
*/
|
|
144 |
const bool affirmative; |
|
145 |
};
|
|
146 |
||
147 |
||
148 |
/**
|
|
149 |
This Item represents a <code>X IS TRUE</code> boolean predicate.
|
|
150 |
*/
|
|
151 |
||
152 |
class Item_func_istrue : public Item_func_truth |
|
153 |
{
|
|
154 |
public: |
|
155 |
Item_func_istrue(Item *a) : Item_func_truth(a, true, true) {} |
|
156 |
~Item_func_istrue() {} |
|
157 |
virtual const char* func_name() const { return "istrue"; } |
|
158 |
};
|
|
159 |
||
160 |
||
161 |
/**
|
|
162 |
This Item represents a <code>X IS NOT TRUE</code> boolean predicate.
|
|
163 |
*/
|
|
164 |
||
165 |
class Item_func_isnottrue : public Item_func_truth |
|
166 |
{
|
|
167 |
public: |
|
168 |
Item_func_isnottrue(Item *a) : Item_func_truth(a, true, false) {} |
|
169 |
~Item_func_isnottrue() {} |
|
170 |
virtual const char* func_name() const { return "isnottrue"; } |
|
171 |
};
|
|
172 |
||
173 |
||
174 |
/**
|
|
175 |
This Item represents a <code>X IS FALSE</code> boolean predicate.
|
|
176 |
*/
|
|
177 |
||
178 |
class Item_func_isfalse : public Item_func_truth |
|
179 |
{
|
|
180 |
public: |
|
181 |
Item_func_isfalse(Item *a) : Item_func_truth(a, false, true) {} |
|
182 |
~Item_func_isfalse() {} |
|
183 |
virtual const char* func_name() const { return "isfalse"; } |
|
184 |
};
|
|
185 |
||
186 |
||
187 |
/**
|
|
188 |
This Item represents a <code>X IS NOT FALSE</code> boolean predicate.
|
|
189 |
*/
|
|
190 |
||
191 |
class Item_func_isnotfalse : public Item_func_truth |
|
192 |
{
|
|
193 |
public: |
|
194 |
Item_func_isnotfalse(Item *a) : Item_func_truth(a, false, false) {} |
|
195 |
~Item_func_isnotfalse() {} |
|
196 |
virtual const char* func_name() const { return "isnotfalse"; } |
|
197 |
};
|
|
198 |
||
199 |
||
200 |
class Item_cache; |
|
275
by Brian Aker
Full removal of my_bool from central server. |
201 |
#define UNKNOWN ((bool)-1)
|
1
by brian
clean slate |
202 |
|
203 |
||
204 |
/*
|
|
205 |
Item_in_optimizer(left_expr, Item_in_subselect(...))
|
|
206 |
||
207 |
Item_in_optimizer is used to wrap an instance of Item_in_subselect. This
|
|
208 |
class does the following:
|
|
209 |
- Evaluate the left expression and store it in Item_cache_* object (to
|
|
210 |
avoid re-evaluating it many times during subquery execution)
|
|
211 |
- Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we
|
|
212 |
don't care if the result is NULL or FALSE.
|
|
213 |
||
214 |
NOTE
|
|
215 |
It is not quite clear why the above listed functionality should be
|
|
216 |
placed into a separate class called 'Item_in_optimizer'.
|
|
217 |
*/
|
|
218 |
||
219 |
class Item_in_optimizer: public Item_bool_func |
|
220 |
{
|
|
221 |
protected: |
|
222 |
Item_cache *cache; |
|
223 |
bool save_cache; |
|
224 |
/*
|
|
225 |
Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries:
|
|
226 |
UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated
|
|
227 |
FALSE - result is FALSE
|
|
228 |
TRUE - result is NULL
|
|
229 |
*/
|
|
275
by Brian Aker
Full removal of my_bool from central server. |
230 |
bool result_for_null_param; |
1
by brian
clean slate |
231 |
public: |
232 |
Item_in_optimizer(Item *a, Item_in_subselect *b): |
|
233 |
Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), |
|
234 |
save_cache(0), result_for_null_param(UNKNOWN) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
235 |
{ with_subselect= true; } |
1
by brian
clean slate |
236 |
bool fix_fields(THD *, Item **); |
237 |
bool fix_left(THD *thd, Item **ref); |
|
238 |
bool is_null(); |
|
152
by Brian Aker
longlong replacement |
239 |
int64_t val_int(); |
1
by brian
clean slate |
240 |
void cleanup(); |
241 |
const char *func_name() const { return "<in_optimizer>"; } |
|
242 |
Item_cache **get_cache() { return &cache; } |
|
243 |
void keep_top_level_cache(); |
|
244 |
Item *transform(Item_transformer transformer, uchar *arg); |
|
245 |
};
|
|
246 |
||
247 |
class Comp_creator |
|
248 |
{
|
|
249 |
public: |
|
250 |
Comp_creator() {} /* Remove gcc warning */ |
|
251 |
virtual ~Comp_creator() {} /* Remove gcc warning */ |
|
252 |
virtual Item_bool_func2* create(Item *a, Item *b) const = 0; |
|
253 |
virtual const char* symbol(bool invert) const = 0; |
|
254 |
virtual bool eqne_op() const = 0; |
|
255 |
virtual bool l_op() const = 0; |
|
256 |
};
|
|
257 |
||
258 |
class Eq_creator :public Comp_creator |
|
259 |
{
|
|
260 |
public: |
|
261 |
Eq_creator() {} /* Remove gcc warning */ |
|
262 |
virtual ~Eq_creator() {} /* Remove gcc warning */ |
|
263 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
264 |
virtual const char* symbol(bool invert) const { return invert? "<>" : "="; } |
|
265 |
virtual bool eqne_op() const { return 1; } |
|
266 |
virtual bool l_op() const { return 0; } |
|
267 |
};
|
|
268 |
||
269 |
class Ne_creator :public Comp_creator |
|
270 |
{
|
|
271 |
public: |
|
272 |
Ne_creator() {} /* Remove gcc warning */ |
|
273 |
virtual ~Ne_creator() {} /* Remove gcc warning */ |
|
274 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
275 |
virtual const char* symbol(bool invert) const { return invert? "=" : "<>"; } |
|
276 |
virtual bool eqne_op() const { return 1; } |
|
277 |
virtual bool l_op() const { return 0; } |
|
278 |
};
|
|
279 |
||
280 |
class Gt_creator :public Comp_creator |
|
281 |
{
|
|
282 |
public: |
|
283 |
Gt_creator() {} /* Remove gcc warning */ |
|
284 |
virtual ~Gt_creator() {} /* Remove gcc warning */ |
|
285 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
286 |
virtual const char* symbol(bool invert) const { return invert? "<=" : ">"; } |
|
287 |
virtual bool eqne_op() const { return 0; } |
|
288 |
virtual bool l_op() const { return 0; } |
|
289 |
};
|
|
290 |
||
291 |
class Lt_creator :public Comp_creator |
|
292 |
{
|
|
293 |
public: |
|
294 |
Lt_creator() {} /* Remove gcc warning */ |
|
295 |
virtual ~Lt_creator() {} /* Remove gcc warning */ |
|
296 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
297 |
virtual const char* symbol(bool invert) const { return invert? ">=" : "<"; } |
|
298 |
virtual bool eqne_op() const { return 0; } |
|
299 |
virtual bool l_op() const { return 1; } |
|
300 |
};
|
|
301 |
||
302 |
class Ge_creator :public Comp_creator |
|
303 |
{
|
|
304 |
public: |
|
305 |
Ge_creator() {} /* Remove gcc warning */ |
|
306 |
virtual ~Ge_creator() {} /* Remove gcc warning */ |
|
307 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
308 |
virtual const char* symbol(bool invert) const { return invert? "<" : ">="; } |
|
309 |
virtual bool eqne_op() const { return 0; } |
|
310 |
virtual bool l_op() const { return 0; } |
|
311 |
};
|
|
312 |
||
313 |
class Le_creator :public Comp_creator |
|
314 |
{
|
|
315 |
public: |
|
316 |
Le_creator() {} /* Remove gcc warning */ |
|
317 |
virtual ~Le_creator() {} /* Remove gcc warning */ |
|
318 |
virtual Item_bool_func2* create(Item *a, Item *b) const; |
|
319 |
virtual const char* symbol(bool invert) const { return invert? ">" : "<="; } |
|
320 |
virtual bool eqne_op() const { return 0; } |
|
321 |
virtual bool l_op() const { return 1; } |
|
322 |
};
|
|
323 |
||
324 |
class Item_bool_func2 :public Item_int_func |
|
325 |
{ /* Bool with 2 string args */ |
|
326 |
protected: |
|
327 |
Arg_comparator cmp; |
|
328 |
String tmp_value1,tmp_value2; |
|
329 |
bool abort_on_null; |
|
330 |
||
331 |
public: |
|
332 |
Item_bool_func2(Item *a,Item *b) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
333 |
:Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(false) {} |
1
by brian
clean slate |
334 |
void fix_length_and_dec(); |
335 |
void set_cmp_func() |
|
336 |
{
|
|
337 |
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1); |
|
338 |
}
|
|
339 |
optimize_type select_optimize() const { return OPTIMIZE_OP; } |
|
340 |
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } |
|
341 |
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } |
|
342 |
||
343 |
virtual inline void print(String *str, enum_query_type query_type) |
|
344 |
{
|
|
345 |
Item_func::print_op(str, query_type); |
|
346 |
}
|
|
347 |
||
348 |
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } |
|
349 |
bool is_bool_func() { return 1; } |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
350 |
const CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; } |
1
by brian
clean slate |
351 |
uint decimal_precision() const { return 1; } |
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
352 |
void top_level_item() { abort_on_null= true; } |
1
by brian
clean slate |
353 |
|
354 |
friend class Arg_comparator; |
|
355 |
};
|
|
356 |
||
357 |
class Item_bool_rowready_func2 :public Item_bool_func2 |
|
358 |
{
|
|
359 |
public: |
|
360 |
Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b) |
|
361 |
{
|
|
362 |
allowed_arg_cols= 0; // Fetch this value from first argument |
|
363 |
}
|
|
364 |
Item *neg_transformer(THD *thd); |
|
365 |
virtual Item *negated_item(); |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
366 |
bool subst_argument_checker(uchar **arg __attribute__((unused))) |
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
367 |
{ return true; } |
1
by brian
clean slate |
368 |
};
|
369 |
||
370 |
class Item_func_not :public Item_bool_func |
|
371 |
{
|
|
372 |
public: |
|
373 |
Item_func_not(Item *a) :Item_bool_func(a) {} |
|
152
by Brian Aker
longlong replacement |
374 |
int64_t val_int(); |
1
by brian
clean slate |
375 |
enum Functype functype() const { return NOT_FUNC; } |
376 |
const char *func_name() const { return "not"; } |
|
377 |
Item *neg_transformer(THD *thd); |
|
378 |
virtual void print(String *str, enum_query_type query_type); |
|
379 |
};
|
|
380 |
||
381 |
class Item_maxmin_subselect; |
|
382 |
||
383 |
/*
|
|
384 |
trigcond<param>(arg) ::= param? arg : TRUE
|
|
385 |
||
386 |
The class Item_func_trig_cond is used for guarded predicates
|
|
387 |
which are employed only for internal purposes.
|
|
388 |
A guarded predicate is an object consisting of an a regular or
|
|
389 |
a guarded predicate P and a pointer to a boolean guard variable g.
|
|
390 |
A guarded predicate P/g is evaluated to true if the value of the
|
|
391 |
guard g is false, otherwise it is evaluated to the same value that
|
|
392 |
the predicate P: val(P/g)= g ? val(P):true.
|
|
393 |
Guarded predicates allow us to include predicates into a conjunction
|
|
394 |
conditionally. Currently they are utilized for pushed down predicates
|
|
395 |
in queries with outer join operations.
|
|
396 |
||
397 |
In the future, probably, it makes sense to extend this class to
|
|
398 |
the objects consisting of three elements: a predicate P, a pointer
|
|
399 |
to a variable g and a firing value s with following evaluation
|
|
400 |
rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only
|
|
401 |
one item for the objects of the form P/g1/g2...
|
|
402 |
||
403 |
Objects of this class are built only for query execution after
|
|
404 |
the execution plan has been already selected. That's why this
|
|
405 |
class needs only val_int out of generic methods.
|
|
406 |
|
|
407 |
Current uses of Item_func_trig_cond objects:
|
|
408 |
- To wrap selection conditions when executing outer joins
|
|
409 |
- To wrap condition that is pushed down into subquery
|
|
410 |
*/
|
|
411 |
||
412 |
class Item_func_trig_cond: public Item_bool_func |
|
413 |
{
|
|
414 |
bool *trig_var; |
|
415 |
public: |
|
416 |
Item_func_trig_cond(Item *a, bool *f) : Item_bool_func(a) { trig_var= f; } |
|
152
by Brian Aker
longlong replacement |
417 |
int64_t val_int() { return *trig_var ? args[0]->val_int() : 1; } |
1
by brian
clean slate |
418 |
enum Functype functype() const { return TRIG_COND_FUNC; }; |
419 |
const char *func_name() const { return "trigcond"; }; |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
420 |
bool const_item() const { return false; } |
1
by brian
clean slate |
421 |
bool *get_trig_var() { return trig_var; } |
422 |
/* The following is needed for ICP: */
|
|
423 |
table_map used_tables() const { return args[0]->used_tables(); } |
|
424 |
};
|
|
425 |
||
426 |
class Item_func_not_all :public Item_func_not |
|
427 |
{
|
|
428 |
/* allow to check presence of values in max/min optimization */
|
|
429 |
Item_sum_hybrid *test_sum_item; |
|
430 |
Item_maxmin_subselect *test_sub_item; |
|
431 |
||
432 |
bool abort_on_null; |
|
433 |
public: |
|
434 |
bool show; |
|
435 |
||
436 |
Item_func_not_all(Item *a) |
|
437 |
:Item_func_not(a), test_sum_item(0), test_sub_item(0), abort_on_null(0), |
|
438 |
show(0) |
|
439 |
{}
|
|
440 |
virtual void top_level_item() { abort_on_null= 1; } |
|
441 |
bool top_level() { return abort_on_null; } |
|
152
by Brian Aker
longlong replacement |
442 |
int64_t val_int(); |
1
by brian
clean slate |
443 |
enum Functype functype() const { return NOT_ALL_FUNC; } |
444 |
const char *func_name() const { return "<not>"; } |
|
445 |
virtual void print(String *str, enum_query_type query_type); |
|
446 |
void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; }; |
|
447 |
void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; }; |
|
448 |
bool empty_underlying_subquery(); |
|
449 |
Item *neg_transformer(THD *thd); |
|
450 |
};
|
|
451 |
||
452 |
||
453 |
class Item_func_nop_all :public Item_func_not_all |
|
454 |
{
|
|
455 |
public: |
|
456 |
||
457 |
Item_func_nop_all(Item *a) :Item_func_not_all(a) {} |
|
152
by Brian Aker
longlong replacement |
458 |
int64_t val_int(); |
1
by brian
clean slate |
459 |
const char *func_name() const { return "<nop>"; } |
460 |
Item *neg_transformer(THD *thd); |
|
461 |
};
|
|
462 |
||
463 |
||
464 |
class Item_func_eq :public Item_bool_rowready_func2 |
|
465 |
{
|
|
466 |
public: |
|
467 |
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} |
|
152
by Brian Aker
longlong replacement |
468 |
int64_t val_int(); |
1
by brian
clean slate |
469 |
enum Functype functype() const { return EQ_FUNC; } |
470 |
enum Functype rev_functype() const { return EQ_FUNC; } |
|
471 |
cond_result eq_cmp_result() const { return COND_TRUE; } |
|
472 |
const char *func_name() const { return "="; } |
|
473 |
Item *negated_item(); |
|
474 |
};
|
|
475 |
||
476 |
class Item_func_equal :public Item_bool_rowready_func2 |
|
477 |
{
|
|
478 |
public: |
|
479 |
Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; |
|
152
by Brian Aker
longlong replacement |
480 |
int64_t val_int(); |
1
by brian
clean slate |
481 |
void fix_length_and_dec(); |
482 |
table_map not_null_tables() const { return 0; } |
|
483 |
enum Functype functype() const { return EQUAL_FUNC; } |
|
484 |
enum Functype rev_functype() const { return EQUAL_FUNC; } |
|
485 |
cond_result eq_cmp_result() const { return COND_TRUE; } |
|
486 |
const char *func_name() const { return "<=>"; } |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
487 |
Item *neg_transformer(THD *thd __attribute__((unused))) { return 0; } |
1
by brian
clean slate |
488 |
};
|
489 |
||
490 |
||
491 |
class Item_func_ge :public Item_bool_rowready_func2 |
|
492 |
{
|
|
493 |
public: |
|
494 |
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; |
|
152
by Brian Aker
longlong replacement |
495 |
int64_t val_int(); |
1
by brian
clean slate |
496 |
enum Functype functype() const { return GE_FUNC; } |
497 |
enum Functype rev_functype() const { return LE_FUNC; } |
|
498 |
cond_result eq_cmp_result() const { return COND_TRUE; } |
|
499 |
const char *func_name() const { return ">="; } |
|
500 |
Item *negated_item(); |
|
501 |
};
|
|
502 |
||
503 |
||
504 |
class Item_func_gt :public Item_bool_rowready_func2 |
|
505 |
{
|
|
506 |
public: |
|
507 |
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; |
|
152
by Brian Aker
longlong replacement |
508 |
int64_t val_int(); |
1
by brian
clean slate |
509 |
enum Functype functype() const { return GT_FUNC; } |
510 |
enum Functype rev_functype() const { return LT_FUNC; } |
|
511 |
cond_result eq_cmp_result() const { return COND_FALSE; } |
|
512 |
const char *func_name() const { return ">"; } |
|
513 |
Item *negated_item(); |
|
514 |
};
|
|
515 |
||
516 |
||
517 |
class Item_func_le :public Item_bool_rowready_func2 |
|
518 |
{
|
|
519 |
public: |
|
520 |
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; |
|
152
by Brian Aker
longlong replacement |
521 |
int64_t val_int(); |
1
by brian
clean slate |
522 |
enum Functype functype() const { return LE_FUNC; } |
523 |
enum Functype rev_functype() const { return GE_FUNC; } |
|
524 |
cond_result eq_cmp_result() const { return COND_TRUE; } |
|
525 |
const char *func_name() const { return "<="; } |
|
526 |
Item *negated_item(); |
|
527 |
};
|
|
528 |
||
529 |
||
530 |
class Item_func_lt :public Item_bool_rowready_func2 |
|
531 |
{
|
|
532 |
public: |
|
533 |
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} |
|
152
by Brian Aker
longlong replacement |
534 |
int64_t val_int(); |
1
by brian
clean slate |
535 |
enum Functype functype() const { return LT_FUNC; } |
536 |
enum Functype rev_functype() const { return GT_FUNC; } |
|
537 |
cond_result eq_cmp_result() const { return COND_FALSE; } |
|
538 |
const char *func_name() const { return "<"; } |
|
539 |
Item *negated_item(); |
|
540 |
};
|
|
541 |
||
542 |
||
543 |
class Item_func_ne :public Item_bool_rowready_func2 |
|
544 |
{
|
|
545 |
public: |
|
546 |
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} |
|
152
by Brian Aker
longlong replacement |
547 |
int64_t val_int(); |
1
by brian
clean slate |
548 |
enum Functype functype() const { return NE_FUNC; } |
549 |
cond_result eq_cmp_result() const { return COND_FALSE; } |
|
550 |
optimize_type select_optimize() const { return OPTIMIZE_KEY; } |
|
551 |
const char *func_name() const { return "<>"; } |
|
552 |
Item *negated_item(); |
|
553 |
};
|
|
554 |
||
555 |
||
556 |
/*
|
|
557 |
The class Item_func_opt_neg is defined to factor out the functionality
|
|
558 |
common for the classes Item_func_between and Item_func_in. The objects
|
|
559 |
of these classes can express predicates or there negations.
|
|
560 |
The alternative approach would be to create pairs Item_func_between,
|
|
561 |
Item_func_notbetween and Item_func_in, Item_func_notin.
|
|
562 |
||
563 |
*/
|
|
564 |
||
565 |
class Item_func_opt_neg :public Item_int_func |
|
566 |
{
|
|
567 |
public: |
|
568 |
bool negated; /* <=> the item represents NOT <func> */ |
|
569 |
bool pred_level; /* <=> [NOT] <func> is used on a predicate level */ |
|
570 |
public: |
|
571 |
Item_func_opt_neg(Item *a, Item *b, Item *c) |
|
572 |
:Item_int_func(a, b, c), negated(0), pred_level(0) {} |
|
573 |
Item_func_opt_neg(List<Item> &list) |
|
574 |
:Item_int_func(list), negated(0), pred_level(0) {} |
|
575 |
public: |
|
576 |
inline void negate() { negated= !negated; } |
|
577 |
inline void top_level_item() { pred_level= 1; } |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
578 |
Item *neg_transformer(THD *thd __attribute__((unused))) |
1
by brian
clean slate |
579 |
{
|
580 |
negated= !negated; |
|
581 |
return this; |
|
582 |
}
|
|
583 |
bool eq(const Item *item, bool binary_cmp) const; |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
584 |
bool subst_argument_checker(uchar **arg __attribute__((unused))) |
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
585 |
{ return true; } |
1
by brian
clean slate |
586 |
};
|
587 |
||
588 |
||
589 |
class Item_func_between :public Item_func_opt_neg |
|
590 |
{
|
|
591 |
DTCollation cmp_collation; |
|
592 |
public: |
|
593 |
Item_result cmp_type; |
|
594 |
String value0,value1,value2; |
|
595 |
/* TRUE <=> arguments will be compared as dates. */
|
|
596 |
bool compare_as_dates; |
|
597 |
/* Comparators used for DATE/DATETIME comparison. */
|
|
598 |
Arg_comparator ge_cmp, le_cmp; |
|
599 |
Item_func_between(Item *a, Item *b, Item *c) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
600 |
:Item_func_opt_neg(a, b, c), compare_as_dates(false) {} |
152
by Brian Aker
longlong replacement |
601 |
int64_t val_int(); |
1
by brian
clean slate |
602 |
optimize_type select_optimize() const { return OPTIMIZE_KEY; } |
603 |
enum Functype functype() const { return BETWEEN; } |
|
604 |
const char *func_name() const { return "between"; } |
|
605 |
bool fix_fields(THD *, Item **); |
|
606 |
void fix_length_and_dec(); |
|
607 |
virtual void print(String *str, enum_query_type query_type); |
|
608 |
bool is_bool_func() { return 1; } |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
609 |
const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } |
1
by brian
clean slate |
610 |
uint decimal_precision() const { return 1; } |
611 |
};
|
|
612 |
||
613 |
||
614 |
class Item_func_strcmp :public Item_bool_func2 |
|
615 |
{
|
|
616 |
public: |
|
617 |
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {} |
|
152
by Brian Aker
longlong replacement |
618 |
int64_t val_int(); |
1
by brian
clean slate |
619 |
optimize_type select_optimize() const { return OPTIMIZE_NONE; } |
620 |
const char *func_name() const { return "strcmp"; } |
|
621 |
||
622 |
virtual inline void print(String *str, enum_query_type query_type) |
|
623 |
{
|
|
624 |
Item_func::print(str, query_type); |
|
625 |
}
|
|
626 |
};
|
|
627 |
||
628 |
||
629 |
struct interval_range |
|
630 |
{
|
|
631 |
Item_result type; |
|
632 |
double dbl; |
|
633 |
my_decimal dec; |
|
634 |
};
|
|
635 |
||
636 |
class Item_func_interval :public Item_int_func |
|
637 |
{
|
|
638 |
Item_row *row; |
|
275
by Brian Aker
Full removal of my_bool from central server. |
639 |
bool use_decimal_comparison; |
1
by brian
clean slate |
640 |
interval_range *intervals; |
641 |
public: |
|
642 |
Item_func_interval(Item_row *a) |
|
643 |
:Item_int_func(a),row(a),intervals(0) |
|
644 |
{
|
|
645 |
allowed_arg_cols= 0; // Fetch this value from first argument |
|
646 |
}
|
|
152
by Brian Aker
longlong replacement |
647 |
int64_t val_int(); |
1
by brian
clean slate |
648 |
void fix_length_and_dec(); |
649 |
const char *func_name() const { return "interval"; } |
|
650 |
uint decimal_precision() const { return 2; } |
|
651 |
};
|
|
652 |
||
653 |
||
654 |
class Item_func_coalesce :public Item_func_numhybrid |
|
655 |
{
|
|
656 |
protected: |
|
657 |
enum_field_types cached_field_type; |
|
658 |
Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} |
|
659 |
public: |
|
660 |
Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} |
|
661 |
double real_op(); |
|
152
by Brian Aker
longlong replacement |
662 |
int64_t int_op(); |
1
by brian
clean slate |
663 |
String *str_op(String *); |
664 |
my_decimal *decimal_op(my_decimal *); |
|
665 |
void fix_length_and_dec(); |
|
666 |
void find_num_type() {} |
|
667 |
enum Item_result result_type () const { return hybrid_type; } |
|
668 |
const char *func_name() const { return "coalesce"; } |
|
669 |
table_map not_null_tables() const { return 0; } |
|
670 |
enum_field_types field_type() const { return cached_field_type; } |
|
671 |
};
|
|
672 |
||
673 |
||
674 |
class Item_func_ifnull :public Item_func_coalesce |
|
675 |
{
|
|
676 |
protected: |
|
677 |
bool field_type_defined; |
|
678 |
public: |
|
679 |
Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} |
|
680 |
double real_op(); |
|
152
by Brian Aker
longlong replacement |
681 |
int64_t int_op(); |
1
by brian
clean slate |
682 |
String *str_op(String *str); |
683 |
my_decimal *decimal_op(my_decimal *); |
|
684 |
enum_field_types field_type() const; |
|
685 |
void fix_length_and_dec(); |
|
686 |
const char *func_name() const { return "ifnull"; } |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
687 |
Field *tmp_table_field(Table *table); |
1
by brian
clean slate |
688 |
uint decimal_precision() const; |
689 |
};
|
|
690 |
||
691 |
||
692 |
class Item_func_if :public Item_func |
|
693 |
{
|
|
694 |
enum Item_result cached_result_type; |
|
695 |
enum_field_types cached_field_type; |
|
696 |
public: |
|
697 |
Item_func_if(Item *a,Item *b,Item *c) |
|
698 |
:Item_func(a,b,c), cached_result_type(INT_RESULT) |
|
699 |
{}
|
|
700 |
double val_real(); |
|
152
by Brian Aker
longlong replacement |
701 |
int64_t val_int(); |
1
by brian
clean slate |
702 |
String *val_str(String *str); |
703 |
my_decimal *val_decimal(my_decimal *); |
|
704 |
enum Item_result result_type () const { return cached_result_type; } |
|
705 |
enum_field_types field_type() const { return cached_field_type; } |
|
706 |
bool fix_fields(THD *, Item **); |
|
707 |
void fix_length_and_dec(); |
|
708 |
uint decimal_precision() const; |
|
709 |
const char *func_name() const { return "if"; } |
|
710 |
};
|
|
711 |
||
712 |
||
713 |
class Item_func_nullif :public Item_bool_func2 |
|
714 |
{
|
|
715 |
enum Item_result cached_result_type; |
|
716 |
public: |
|
717 |
Item_func_nullif(Item *a,Item *b) |
|
718 |
:Item_bool_func2(a,b), cached_result_type(INT_RESULT) |
|
719 |
{}
|
|
720 |
double val_real(); |
|
152
by Brian Aker
longlong replacement |
721 |
int64_t val_int(); |
1
by brian
clean slate |
722 |
String *val_str(String *str); |
723 |
my_decimal *val_decimal(my_decimal *); |
|
724 |
enum Item_result result_type () const { return cached_result_type; } |
|
725 |
void fix_length_and_dec(); |
|
726 |
uint decimal_precision() const { return args[0]->decimal_precision(); } |
|
727 |
const char *func_name() const { return "nullif"; } |
|
728 |
||
729 |
virtual inline void print(String *str, enum_query_type query_type) |
|
730 |
{
|
|
731 |
Item_func::print(str, query_type); |
|
732 |
}
|
|
733 |
||
734 |
table_map not_null_tables() const { return 0; } |
|
735 |
bool is_null(); |
|
736 |
};
|
|
737 |
||
738 |
||
739 |
/* Functions to handle the optimized IN */
|
|
740 |
||
741 |
||
742 |
/* A vector of values of some type */
|
|
743 |
||
744 |
class in_vector :public Sql_alloc |
|
745 |
{
|
|
746 |
public: |
|
747 |
char *base; |
|
748 |
uint size; |
|
749 |
qsort2_cmp compare; |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
750 |
const CHARSET_INFO *collation; |
1
by brian
clean slate |
751 |
uint count; |
752 |
uint used_count; |
|
753 |
in_vector() {} |
|
754 |
in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
755 |
const CHARSET_INFO * const cmp_coll) |
1
by brian
clean slate |
756 |
:base((char*) sql_calloc(elements*element_length)), |
757 |
size(element_length), compare(cmp_func), collation(cmp_coll), |
|
758 |
count(elements), used_count(elements) {} |
|
759 |
virtual ~in_vector() {} |
|
760 |
virtual void set(uint pos,Item *item)=0; |
|
761 |
virtual uchar *get_value(Item *item)=0; |
|
762 |
void sort() |
|
763 |
{
|
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
764 |
my_qsort2(base,used_count,size,compare, (void *) collation); |
1
by brian
clean slate |
765 |
}
|
766 |
int find(Item *item); |
|
767 |
||
768 |
/*
|
|
769 |
Create an instance of Item_{type} (e.g. Item_decimal) constant object
|
|
770 |
which type allows it to hold an element of this vector without any
|
|
771 |
conversions.
|
|
772 |
The purpose of this function is to be able to get elements of this
|
|
773 |
vector in form of Item_xxx constants without creating Item_xxx object
|
|
774 |
for every array element you get (i.e. this implements "FlyWeight" pattern)
|
|
775 |
*/
|
|
776 |
virtual Item* create_item() { return NULL; } |
|
777 |
||
778 |
/*
|
|
779 |
Store the value at position #pos into provided item object
|
|
780 |
SYNOPSIS
|
|
781 |
value_to_item()
|
|
782 |
pos Index of value to store
|
|
783 |
item Constant item to store value into. The item must be of the same
|
|
784 |
type that create_item() returns.
|
|
785 |
*/
|
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
786 |
virtual void value_to_item(uint pos __attribute__((unused)), |
787 |
Item *item __attribute__((unused))) { } |
|
1
by brian
clean slate |
788 |
|
789 |
/* Compare values number pos1 and pos2 for equality */
|
|
790 |
bool compare_elems(uint pos1, uint pos2) |
|
791 |
{
|
|
792 |
return test(compare(collation, base + pos1*size, base + pos2*size)); |
|
793 |
}
|
|
794 |
virtual Item_result result_type()= 0; |
|
795 |
};
|
|
796 |
||
797 |
class in_string :public in_vector |
|
798 |
{
|
|
799 |
char buff[STRING_BUFFER_USUAL_SIZE]; |
|
800 |
String tmp; |
|
801 |
public: |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
802 |
in_string(uint elements,qsort2_cmp cmp_func, const CHARSET_INFO * const cs); |
1
by brian
clean slate |
803 |
~in_string(); |
804 |
void set(uint pos,Item *item); |
|
805 |
uchar *get_value(Item *item); |
|
806 |
Item* create_item() |
|
807 |
{
|
|
808 |
return new Item_string(collation); |
|
809 |
}
|
|
810 |
void value_to_item(uint pos, Item *item) |
|
811 |
{
|
|
812 |
String *str=((String*) base)+pos; |
|
813 |
Item_string *to= (Item_string*)item; |
|
814 |
to->str_value= *str; |
|
815 |
}
|
|
816 |
Item_result result_type() { return STRING_RESULT; } |
|
817 |
};
|
|
818 |
||
152
by Brian Aker
longlong replacement |
819 |
class in_int64_t :public in_vector |
1
by brian
clean slate |
820 |
{
|
821 |
protected: |
|
822 |
/*
|
|
823 |
Here we declare a temporary variable (tmp) of the same type as the
|
|
824 |
elements of this vector. tmp is used in finding if a given value is in
|
|
825 |
the list.
|
|
826 |
*/
|
|
152
by Brian Aker
longlong replacement |
827 |
struct packed_int64_t |
1
by brian
clean slate |
828 |
{
|
152
by Brian Aker
longlong replacement |
829 |
int64_t val; |
830 |
int64_t unsigned_flag; // Use int64_t, not bool, to preserve alignment |
|
1
by brian
clean slate |
831 |
} tmp; |
832 |
public: |
|
152
by Brian Aker
longlong replacement |
833 |
in_int64_t(uint elements); |
1
by brian
clean slate |
834 |
void set(uint pos,Item *item); |
835 |
uchar *get_value(Item *item); |
|
836 |
||
837 |
Item* create_item() |
|
838 |
{
|
|
839 |
/*
|
|
840 |
We're created a signed INT, this may not be correct in
|
|
841 |
general case (see BUG#19342).
|
|
842 |
*/
|
|
152
by Brian Aker
longlong replacement |
843 |
return new Item_int((int64_t)0); |
1
by brian
clean slate |
844 |
}
|
845 |
void value_to_item(uint pos, Item *item) |
|
846 |
{
|
|
152
by Brian Aker
longlong replacement |
847 |
((Item_int*) item)->value= ((packed_int64_t*) base)[pos].val; |
275
by Brian Aker
Full removal of my_bool from central server. |
848 |
((Item_int*) item)->unsigned_flag= (bool) |
152
by Brian Aker
longlong replacement |
849 |
((packed_int64_t*) base)[pos].unsigned_flag; |
1
by brian
clean slate |
850 |
}
|
851 |
Item_result result_type() { return INT_RESULT; } |
|
852 |
||
152
by Brian Aker
longlong replacement |
853 |
friend int cmp_int64_t(void *cmp_arg, packed_int64_t *a,packed_int64_t *b); |
1
by brian
clean slate |
854 |
};
|
855 |
||
856 |
||
857 |
/*
|
|
858 |
Class to represent a vector of constant DATE/DATETIME values.
|
|
859 |
Values are obtained with help of the get_datetime_value() function.
|
|
860 |
If the left item is a constant one then its value is cached in the
|
|
861 |
lval_cache variable.
|
|
862 |
*/
|
|
152
by Brian Aker
longlong replacement |
863 |
class in_datetime :public in_int64_t |
1
by brian
clean slate |
864 |
{
|
865 |
public: |
|
866 |
THD *thd; |
|
867 |
/* An item used to issue warnings. */
|
|
868 |
Item *warn_item; |
|
869 |
/* Cache for the left item. */
|
|
870 |
Item *lval_cache; |
|
871 |
||
872 |
in_datetime(Item *warn_item_arg, uint elements) |
|
152
by Brian Aker
longlong replacement |
873 |
:in_int64_t(elements), thd(current_thd), warn_item(warn_item_arg), |
1
by brian
clean slate |
874 |
lval_cache(0) {}; |
875 |
void set(uint pos,Item *item); |
|
876 |
uchar *get_value(Item *item); |
|
152
by Brian Aker
longlong replacement |
877 |
friend int cmp_int64_t(void *cmp_arg, packed_int64_t *a,packed_int64_t *b); |
1
by brian
clean slate |
878 |
};
|
879 |
||
880 |
||
881 |
class in_double :public in_vector |
|
882 |
{
|
|
883 |
double tmp; |
|
884 |
public: |
|
885 |
in_double(uint elements); |
|
886 |
void set(uint pos,Item *item); |
|
887 |
uchar *get_value(Item *item); |
|
888 |
Item *create_item() |
|
889 |
{
|
|
890 |
return new Item_float(0.0, 0); |
|
891 |
}
|
|
892 |
void value_to_item(uint pos, Item *item) |
|
893 |
{
|
|
894 |
((Item_float*)item)->value= ((double*) base)[pos]; |
|
895 |
}
|
|
896 |
Item_result result_type() { return REAL_RESULT; } |
|
897 |
};
|
|
898 |
||
899 |
||
900 |
class in_decimal :public in_vector |
|
901 |
{
|
|
902 |
my_decimal val; |
|
903 |
public: |
|
904 |
in_decimal(uint elements); |
|
905 |
void set(uint pos, Item *item); |
|
906 |
uchar *get_value(Item *item); |
|
907 |
Item *create_item() |
|
908 |
{
|
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
909 |
return new Item_decimal(0, false); |
1
by brian
clean slate |
910 |
}
|
911 |
void value_to_item(uint pos, Item *item) |
|
912 |
{
|
|
913 |
my_decimal *dec= ((my_decimal *)base) + pos; |
|
914 |
Item_decimal *item_dec= (Item_decimal*)item; |
|
915 |
item_dec->set_decimal_value(dec); |
|
916 |
}
|
|
917 |
Item_result result_type() { return DECIMAL_RESULT; } |
|
918 |
||
919 |
};
|
|
920 |
||
921 |
||
922 |
/*
|
|
923 |
** Classes for easy comparing of non const items
|
|
924 |
*/
|
|
925 |
||
926 |
class cmp_item :public Sql_alloc |
|
927 |
{
|
|
928 |
public: |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
929 |
const CHARSET_INFO *cmp_charset; |
1
by brian
clean slate |
930 |
cmp_item() { cmp_charset= &my_charset_bin; } |
931 |
virtual ~cmp_item() {} |
|
932 |
virtual void store_value(Item *item)= 0; |
|
933 |
virtual int cmp(Item *item)= 0; |
|
934 |
// for optimized IN with row
|
|
935 |
virtual int compare(cmp_item *item)= 0; |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
936 |
static cmp_item* get_comparator(Item_result type, const CHARSET_INFO * const cs); |
1
by brian
clean slate |
937 |
virtual cmp_item *make_same()= 0; |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
938 |
virtual void store_value_by_template(cmp_item *tmpl __attribute__((unused)), |
77.1.7
by Monty Taylor
Heap builds clean. |
939 |
Item *item) |
1
by brian
clean slate |
940 |
{
|
941 |
store_value(item); |
|
942 |
}
|
|
943 |
};
|
|
944 |
||
945 |
class cmp_item_string :public cmp_item |
|
946 |
{
|
|
947 |
protected: |
|
948 |
String *value_res; |
|
949 |
public: |
|
950 |
cmp_item_string () {} |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
951 |
cmp_item_string (const CHARSET_INFO * const cs) { cmp_charset= cs; } |
952 |
void set_charset(const CHARSET_INFO * const cs) { cmp_charset= cs; } |
|
1
by brian
clean slate |
953 |
friend class cmp_item_sort_string; |
954 |
friend class cmp_item_sort_string_in_static; |
|
955 |
};
|
|
956 |
||
957 |
class cmp_item_sort_string :public cmp_item_string |
|
958 |
{
|
|
959 |
protected: |
|
960 |
char value_buff[STRING_BUFFER_USUAL_SIZE]; |
|
961 |
String value; |
|
962 |
public: |
|
963 |
cmp_item_sort_string(): |
|
964 |
cmp_item_string() {} |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
965 |
cmp_item_sort_string(const CHARSET_INFO * const cs): |
1
by brian
clean slate |
966 |
cmp_item_string(cs), |
967 |
value(value_buff, sizeof(value_buff), cs) {} |
|
968 |
void store_value(Item *item) |
|
969 |
{
|
|
970 |
value_res= item->val_str(&value); |
|
971 |
}
|
|
972 |
int cmp(Item *arg) |
|
973 |
{
|
|
974 |
char buff[STRING_BUFFER_USUAL_SIZE]; |
|
975 |
String tmp(buff, sizeof(buff), cmp_charset), *res; |
|
976 |
res= arg->val_str(&tmp); |
|
977 |
return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) : |
|
978 |
(res ? -1 : 0)); |
|
979 |
}
|
|
980 |
int compare(cmp_item *ci) |
|
981 |
{
|
|
982 |
cmp_item_string *l_cmp= (cmp_item_string *) ci; |
|
983 |
return sortcmp(value_res, l_cmp->value_res, cmp_charset); |
|
984 |
}
|
|
985 |
cmp_item *make_same(); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
986 |
void set_charset(const CHARSET_INFO * const cs) |
1
by brian
clean slate |
987 |
{
|
988 |
cmp_charset= cs; |
|
989 |
value.set_quick(value_buff, sizeof(value_buff), cs); |
|
990 |
}
|
|
991 |
};
|
|
992 |
||
993 |
class cmp_item_int :public cmp_item |
|
994 |
{
|
|
152
by Brian Aker
longlong replacement |
995 |
int64_t value; |
1
by brian
clean slate |
996 |
public: |
997 |
cmp_item_int() {} /* Remove gcc warning */ |
|
998 |
void store_value(Item *item) |
|
999 |
{
|
|
1000 |
value= item->val_int(); |
|
1001 |
}
|
|
1002 |
int cmp(Item *arg) |
|
1003 |
{
|
|
1004 |
return value != arg->val_int(); |
|
1005 |
}
|
|
1006 |
int compare(cmp_item *ci) |
|
1007 |
{
|
|
1008 |
cmp_item_int *l_cmp= (cmp_item_int *)ci; |
|
1009 |
return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1); |
|
1010 |
}
|
|
1011 |
cmp_item *make_same(); |
|
1012 |
};
|
|
1013 |
||
1014 |
/*
|
|
1015 |
Compare items in the DATETIME context.
|
|
1016 |
Values are obtained with help of the get_datetime_value() function.
|
|
1017 |
If the left item is a constant one then its value is cached in the
|
|
1018 |
lval_cache variable.
|
|
1019 |
*/
|
|
1020 |
class cmp_item_datetime :public cmp_item |
|
1021 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
1022 |
uint64_t value; |
1
by brian
clean slate |
1023 |
public: |
1024 |
THD *thd; |
|
1025 |
/* Item used for issuing warnings. */
|
|
1026 |
Item *warn_item; |
|
1027 |
/* Cache for the left item. */
|
|
1028 |
Item *lval_cache; |
|
1029 |
||
1030 |
cmp_item_datetime(Item *warn_item_arg) |
|
1031 |
:thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {} |
|
1032 |
void store_value(Item *item); |
|
1033 |
int cmp(Item *arg); |
|
1034 |
int compare(cmp_item *ci); |
|
1035 |
cmp_item *make_same(); |
|
1036 |
};
|
|
1037 |
||
1038 |
class cmp_item_real :public cmp_item |
|
1039 |
{
|
|
1040 |
double value; |
|
1041 |
public: |
|
1042 |
cmp_item_real() {} /* Remove gcc warning */ |
|
1043 |
void store_value(Item *item) |
|
1044 |
{
|
|
1045 |
value= item->val_real(); |
|
1046 |
}
|
|
1047 |
int cmp(Item *arg) |
|
1048 |
{
|
|
1049 |
return value != arg->val_real(); |
|
1050 |
}
|
|
1051 |
int compare(cmp_item *ci) |
|
1052 |
{
|
|
1053 |
cmp_item_real *l_cmp= (cmp_item_real *) ci; |
|
1054 |
return (value < l_cmp->value)? -1 : ((value == l_cmp->value) ? 0 : 1); |
|
1055 |
}
|
|
1056 |
cmp_item *make_same(); |
|
1057 |
};
|
|
1058 |
||
1059 |
||
1060 |
class cmp_item_decimal :public cmp_item |
|
1061 |
{
|
|
1062 |
my_decimal value; |
|
1063 |
public: |
|
1064 |
cmp_item_decimal() {} /* Remove gcc warning */ |
|
1065 |
void store_value(Item *item); |
|
1066 |
int cmp(Item *arg); |
|
1067 |
int compare(cmp_item *c); |
|
1068 |
cmp_item *make_same(); |
|
1069 |
};
|
|
1070 |
||
1071 |
||
1072 |
/*
|
|
1073 |
cmp_item for optimized IN with row (right part string, which never
|
|
1074 |
be changed)
|
|
1075 |
*/
|
|
1076 |
||
1077 |
class cmp_item_sort_string_in_static :public cmp_item_string |
|
1078 |
{
|
|
1079 |
protected: |
|
1080 |
String value; |
|
1081 |
public: |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1082 |
cmp_item_sort_string_in_static(const CHARSET_INFO * const cs): |
1
by brian
clean slate |
1083 |
cmp_item_string(cs) {} |
1084 |
void store_value(Item *item) |
|
1085 |
{
|
|
1086 |
value_res= item->val_str(&value); |
|
1087 |
}
|
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
1088 |
int cmp(Item *item __attribute__((unused))) |
1
by brian
clean slate |
1089 |
{
|
1090 |
// Should never be called
|
|
51.1.17
by Jay Pipes
Removed/replaced DBUG symbols |
1091 |
assert(0); |
1
by brian
clean slate |
1092 |
return 1; |
1093 |
}
|
|
1094 |
int compare(cmp_item *ci) |
|
1095 |
{
|
|
1096 |
cmp_item_string *l_cmp= (cmp_item_string *) ci; |
|
1097 |
return sortcmp(value_res, l_cmp->value_res, cmp_charset); |
|
1098 |
}
|
|
1099 |
cmp_item *make_same() |
|
1100 |
{
|
|
1101 |
return new cmp_item_sort_string_in_static(cmp_charset); |
|
1102 |
}
|
|
1103 |
};
|
|
1104 |
||
1105 |
||
1106 |
/*
|
|
1107 |
The class Item_func_case is the CASE ... WHEN ... THEN ... END function
|
|
1108 |
implementation.
|
|
1109 |
||
1110 |
When there is no expression between CASE and the first WHEN
|
|
1111 |
(the CASE expression) then this function simple checks all WHEN expressions
|
|
1112 |
one after another. When some WHEN expression evaluated to TRUE then the
|
|
1113 |
value of the corresponding THEN expression is returned.
|
|
1114 |
||
1115 |
When the CASE expression is specified then it is compared to each WHEN
|
|
1116 |
expression individually. When an equal WHEN expression is found
|
|
1117 |
corresponding THEN expression is returned.
|
|
1118 |
In order to do correct comparisons several comparators are used. One for
|
|
1119 |
each result type. Different result types that are used in particular
|
|
1120 |
CASE ... END expression are collected in the fix_length_and_dec() member
|
|
1121 |
function and only comparators for there result types are used.
|
|
1122 |
*/
|
|
1123 |
||
1124 |
class Item_func_case :public Item_func |
|
1125 |
{
|
|
1126 |
int first_expr_num, else_expr_num; |
|
1127 |
enum Item_result cached_result_type, left_result_type; |
|
1128 |
String tmp_value; |
|
1129 |
uint ncases; |
|
1130 |
Item_result cmp_type; |
|
1131 |
DTCollation cmp_collation; |
|
1132 |
enum_field_types cached_field_type; |
|
1133 |
cmp_item *cmp_items[5]; /* For all result types */ |
|
1134 |
cmp_item *case_item; |
|
1135 |
public: |
|
1136 |
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg) |
|
1137 |
:Item_func(), first_expr_num(-1), else_expr_num(-1), |
|
1138 |
cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0) |
|
1139 |
{
|
|
1140 |
ncases= list.elements; |
|
1141 |
if (first_expr_arg) |
|
1142 |
{
|
|
1143 |
first_expr_num= list.elements; |
|
1144 |
list.push_back(first_expr_arg); |
|
1145 |
}
|
|
1146 |
if (else_expr_arg) |
|
1147 |
{
|
|
1148 |
else_expr_num= list.elements; |
|
1149 |
list.push_back(else_expr_arg); |
|
1150 |
}
|
|
1151 |
set_arguments(list); |
|
212.6.1
by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file. |
1152 |
memset(&cmp_items, 0, sizeof(cmp_items)); |
1
by brian
clean slate |
1153 |
}
|
1154 |
double val_real(); |
|
152
by Brian Aker
longlong replacement |
1155 |
int64_t val_int(); |
1
by brian
clean slate |
1156 |
String *val_str(String *); |
1157 |
my_decimal *val_decimal(my_decimal *); |
|
1158 |
bool fix_fields(THD *thd, Item **ref); |
|
1159 |
void fix_length_and_dec(); |
|
1160 |
uint decimal_precision() const; |
|
1161 |
table_map not_null_tables() const { return 0; } |
|
1162 |
enum Item_result result_type () const { return cached_result_type; } |
|
1163 |
enum_field_types field_type() const { return cached_field_type; } |
|
1164 |
const char *func_name() const { return "case"; } |
|
1165 |
virtual void print(String *str, enum_query_type query_type); |
|
1166 |
Item *find_item(String *str); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1167 |
const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } |
1
by brian
clean slate |
1168 |
void cleanup(); |
1169 |
void agg_str_lengths(Item *arg); |
|
1170 |
void agg_num_lengths(Item *arg); |
|
1171 |
};
|
|
1172 |
||
1173 |
/*
|
|
1174 |
The Item_func_in class implements the in_expr IN(values_list) function.
|
|
1175 |
||
1176 |
The current implementation distinguishes 2 cases:
|
|
1177 |
1) all items in the value_list are constants and have the same
|
|
1178 |
result type. This case is handled by in_vector class.
|
|
1179 |
2) items in the value_list have different result types or there is some
|
|
1180 |
non-constant items.
|
|
1181 |
In this case Item_func_in employs several cmp_item objects to performs
|
|
1182 |
comparisons of in_expr and an item from the values_list. One cmp_item
|
|
1183 |
object for each result type. Different result types are collected in the
|
|
1184 |
fix_length_and_dec() member function by means of collect_cmp_types()
|
|
1185 |
function.
|
|
1186 |
*/
|
|
1187 |
class Item_func_in :public Item_func_opt_neg |
|
1188 |
{
|
|
1189 |
public: |
|
1190 |
/*
|
|
1191 |
an array of values when the right hand arguments of IN
|
|
1192 |
are all SQL constant and there are no nulls
|
|
1193 |
*/
|
|
1194 |
in_vector *array; |
|
1195 |
bool have_null; |
|
1196 |
/*
|
|
1197 |
true when all arguments of the IN clause are of compatible types
|
|
1198 |
and can be used safely as comparisons for key conditions
|
|
1199 |
*/
|
|
1200 |
bool arg_types_compatible; |
|
1201 |
Item_result left_result_type; |
|
1202 |
cmp_item *cmp_items[6]; /* One cmp_item for each result type */ |
|
1203 |
DTCollation cmp_collation; |
|
1204 |
||
1205 |
Item_func_in(List<Item> &list) |
|
1206 |
:Item_func_opt_neg(list), array(0), have_null(0), |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
1207 |
arg_types_compatible(false) |
1
by brian
clean slate |
1208 |
{
|
212.6.1
by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file. |
1209 |
memset(&cmp_items, 0, sizeof(cmp_items)); |
1
by brian
clean slate |
1210 |
allowed_arg_cols= 0; // Fetch this value from first argument |
1211 |
}
|
|
152
by Brian Aker
longlong replacement |
1212 |
int64_t val_int(); |
1
by brian
clean slate |
1213 |
bool fix_fields(THD *, Item **); |
1214 |
void fix_length_and_dec(); |
|
1215 |
uint decimal_precision() const { return 1; } |
|
1216 |
void cleanup() |
|
1217 |
{
|
|
1218 |
uint i; |
|
1219 |
Item_int_func::cleanup(); |
|
1220 |
delete array; |
|
1221 |
array= 0; |
|
1222 |
for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++) |
|
1223 |
{
|
|
1224 |
delete cmp_items[i]; |
|
1225 |
cmp_items[i]= 0; |
|
1226 |
}
|
|
51.1.17
by Jay Pipes
Removed/replaced DBUG symbols |
1227 |
return; |
1
by brian
clean slate |
1228 |
}
|
1229 |
optimize_type select_optimize() const |
|
1230 |
{ return OPTIMIZE_KEY; } |
|
1231 |
virtual void print(String *str, enum_query_type query_type); |
|
1232 |
enum Functype functype() const { return IN_FUNC; } |
|
1233 |
const char *func_name() const { return " IN "; } |
|
1234 |
bool nulls_in_row(); |
|
1235 |
bool is_bool_func() { return 1; } |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1236 |
const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } |
1
by brian
clean slate |
1237 |
};
|
1238 |
||
1239 |
class cmp_item_row :public cmp_item |
|
1240 |
{
|
|
1241 |
cmp_item **comparators; |
|
1242 |
uint n; |
|
1243 |
public: |
|
1244 |
cmp_item_row(): comparators(0), n(0) {} |
|
1245 |
~cmp_item_row(); |
|
1246 |
void store_value(Item *item); |
|
1247 |
inline void alloc_comparators(); |
|
1248 |
int cmp(Item *arg); |
|
1249 |
int compare(cmp_item *arg); |
|
1250 |
cmp_item *make_same(); |
|
1251 |
void store_value_by_template(cmp_item *tmpl, Item *); |
|
1252 |
friend void Item_func_in::fix_length_and_dec(); |
|
1253 |
};
|
|
1254 |
||
1255 |
||
1256 |
class in_row :public in_vector |
|
1257 |
{
|
|
1258 |
cmp_item_row tmp; |
|
1259 |
public: |
|
1260 |
in_row(uint elements, Item *); |
|
1261 |
~in_row(); |
|
1262 |
void set(uint pos,Item *item); |
|
1263 |
uchar *get_value(Item *item); |
|
1264 |
friend void Item_func_in::fix_length_and_dec(); |
|
1265 |
Item_result result_type() { return ROW_RESULT; } |
|
1266 |
};
|
|
1267 |
||
1268 |
/* Functions used by where clause */
|
|
1269 |
||
1270 |
class Item_func_isnull :public Item_bool_func |
|
1271 |
{
|
|
1272 |
protected: |
|
152
by Brian Aker
longlong replacement |
1273 |
int64_t cached_value; |
1
by brian
clean slate |
1274 |
public: |
1275 |
Item_func_isnull(Item *a) :Item_bool_func(a) {} |
|
152
by Brian Aker
longlong replacement |
1276 |
int64_t val_int(); |
1
by brian
clean slate |
1277 |
enum Functype functype() const { return ISNULL_FUNC; } |
1278 |
void fix_length_and_dec() |
|
1279 |
{
|
|
1280 |
decimals=0; max_length=1; maybe_null=0; |
|
1281 |
update_used_tables(); |
|
1282 |
}
|
|
1283 |
const char *func_name() const { return "isnull"; } |
|
1284 |
/* Optimize case of not_null_column IS NULL */
|
|
1285 |
virtual void update_used_tables() |
|
1286 |
{
|
|
1287 |
if (!args[0]->maybe_null) |
|
1288 |
{
|
|
1289 |
used_tables_cache= 0; /* is always false */ |
|
1290 |
const_item_cache= 1; |
|
152
by Brian Aker
longlong replacement |
1291 |
cached_value= (int64_t) 0; |
1
by brian
clean slate |
1292 |
}
|
1293 |
else
|
|
1294 |
{
|
|
1295 |
args[0]->update_used_tables(); |
|
1296 |
if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())) && |
|
1297 |
!with_subselect) |
|
1298 |
{
|
|
1299 |
/* Remember if the value is always NULL or never NULL */
|
|
152
by Brian Aker
longlong replacement |
1300 |
cached_value= (int64_t) args[0]->is_null(); |
1
by brian
clean slate |
1301 |
}
|
1302 |
}
|
|
1303 |
}
|
|
1304 |
table_map not_null_tables() const { return 0; } |
|
1305 |
optimize_type select_optimize() const { return OPTIMIZE_NULL; } |
|
1306 |
Item *neg_transformer(THD *thd); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1307 |
const CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } |
1
by brian
clean slate |
1308 |
};
|
1309 |
||
1310 |
/* Functions used by HAVING for rewriting IN subquery */
|
|
1311 |
||
1312 |
class Item_in_subselect; |
|
1313 |
||
1314 |
/*
|
|
1315 |
This is like IS NOT NULL but it also remembers if it ever has
|
|
1316 |
encountered a NULL.
|
|
1317 |
*/
|
|
1318 |
class Item_is_not_null_test :public Item_func_isnull |
|
1319 |
{
|
|
1320 |
Item_in_subselect* owner; |
|
1321 |
public: |
|
1322 |
Item_is_not_null_test(Item_in_subselect* ow, Item *a) |
|
1323 |
:Item_func_isnull(a), owner(ow) |
|
1324 |
{}
|
|
1325 |
enum Functype functype() const { return ISNOTNULLTEST_FUNC; } |
|
152
by Brian Aker
longlong replacement |
1326 |
int64_t val_int(); |
1
by brian
clean slate |
1327 |
const char *func_name() const { return "<is_not_null_test>"; } |
1328 |
void update_used_tables(); |
|
1329 |
/*
|
|
1330 |
we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
|
|
1331 |
*/
|
|
1332 |
table_map used_tables() const |
|
1333 |
{ return used_tables_cache | RAND_TABLE_BIT; } |
|
1334 |
};
|
|
1335 |
||
1336 |
||
1337 |
class Item_func_isnotnull :public Item_bool_func |
|
1338 |
{
|
|
1339 |
bool abort_on_null; |
|
1340 |
public: |
|
1341 |
Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0) {} |
|
152
by Brian Aker
longlong replacement |
1342 |
int64_t val_int(); |
1
by brian
clean slate |
1343 |
enum Functype functype() const { return ISNOTNULL_FUNC; } |
1344 |
void fix_length_and_dec() |
|
1345 |
{
|
|
1346 |
decimals=0; max_length=1; maybe_null=0; |
|
1347 |
}
|
|
1348 |
const char *func_name() const { return "isnotnull"; } |
|
1349 |
optimize_type select_optimize() const { return OPTIMIZE_NULL; } |
|
1350 |
table_map not_null_tables() const |
|
1351 |
{ return abort_on_null ? not_null_tables_cache : 0; } |
|
1352 |
Item *neg_transformer(THD *thd); |
|
1353 |
virtual void print(String *str, enum_query_type query_type); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1354 |
const CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } |
1
by brian
clean slate |
1355 |
void top_level_item() { abort_on_null=1; } |
1356 |
};
|
|
1357 |
||
1358 |
||
1359 |
class Item_func_like :public Item_bool_func2 |
|
1360 |
{
|
|
1361 |
// Turbo Boyer-Moore data
|
|
1362 |
bool canDoTurboBM; // pattern is '%abcd%' case |
|
1363 |
const char* pattern; |
|
1364 |
int pattern_len; |
|
1365 |
||
1366 |
// TurboBM buffers, *this is owner
|
|
1367 |
int* bmGs; // good suffix shift table, size is pattern_len + 1 |
|
1368 |
int* bmBc; // bad character shift table, size is alphabet_size |
|
1369 |
||
1370 |
void turboBM_compute_suffixes(int* suff); |
|
1371 |
void turboBM_compute_good_suffix_shifts(int* suff); |
|
1372 |
void turboBM_compute_bad_character_shifts(); |
|
1373 |
bool turboBM_matches(const char* text, int text_len) const; |
|
1374 |
enum { alphabet_size = 256 }; |
|
1375 |
||
1376 |
Item *escape_item; |
|
1377 |
||
1378 |
bool escape_used_in_parsing; |
|
1379 |
||
1380 |
public: |
|
1381 |
int escape; |
|
1382 |
||
1383 |
Item_func_like(Item *a,Item *b, Item *escape_arg, bool escape_used) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
1384 |
:Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0), |
1
by brian
clean slate |
1385 |
bmGs(0), bmBc(0), escape_item(escape_arg), |
1386 |
escape_used_in_parsing(escape_used) {} |
|
152
by Brian Aker
longlong replacement |
1387 |
int64_t val_int(); |
1
by brian
clean slate |
1388 |
enum Functype functype() const { return LIKE_FUNC; } |
1389 |
optimize_type select_optimize() const; |
|
1390 |
cond_result eq_cmp_result() const { return COND_TRUE; } |
|
1391 |
const char *func_name() const { return "like"; } |
|
1392 |
bool fix_fields(THD *thd, Item **ref); |
|
1393 |
void cleanup(); |
|
1394 |
};
|
|
1395 |
||
1396 |
||
1397 |
typedef class Item COND; |
|
1398 |
||
1399 |
class Item_cond :public Item_bool_func |
|
1400 |
{
|
|
1401 |
protected: |
|
1402 |
List<Item> list; |
|
1403 |
bool abort_on_null; |
|
1404 |
table_map and_tables_cache; |
|
1405 |
||
1406 |
public: |
|
1407 |
/* Item_cond() is only used to create top level items */
|
|
1408 |
Item_cond(): Item_bool_func(), abort_on_null(1) |
|
1409 |
{ const_item_cache=0; } |
|
1410 |
Item_cond(Item *i1,Item *i2) |
|
1411 |
:Item_bool_func(), abort_on_null(0) |
|
1412 |
{
|
|
1413 |
list.push_back(i1); |
|
1414 |
list.push_back(i2); |
|
1415 |
}
|
|
1416 |
Item_cond(THD *thd, Item_cond *item); |
|
1417 |
Item_cond(List<Item> &nlist) |
|
1418 |
:Item_bool_func(), list(nlist), abort_on_null(0) {} |
|
1419 |
bool add(Item *item) { return list.push_back(item); } |
|
1420 |
bool add_at_head(Item *item) { return list.push_front(item); } |
|
1421 |
void add_at_head(List<Item> *nlist) { list.prepand(nlist); } |
|
1422 |
bool fix_fields(THD *, Item **ref); |
|
1423 |
void fix_after_pullout(st_select_lex *new_parent, Item **ref); |
|
1424 |
||
1425 |
enum Type type() const { return COND_ITEM; } |
|
1426 |
List<Item>* argument_list() { return &list; } |
|
1427 |
table_map used_tables() const; |
|
1428 |
void update_used_tables(); |
|
1429 |
virtual void print(String *str, enum_query_type query_type); |
|
1430 |
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields); |
|
327.2.4
by Brian Aker
Refactoring table.h |
1431 |
friend int setup_conds(THD *thd, TableList *tables, TableList *leaves, |
1
by brian
clean slate |
1432 |
COND **conds); |
1433 |
void top_level_item() { abort_on_null=1; } |
|
1434 |
void copy_andor_arguments(THD *thd, Item_cond *item); |
|
1435 |
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); |
|
1436 |
Item *transform(Item_transformer transformer, uchar *arg); |
|
1437 |
void traverse_cond(Cond_traverser, void *arg, traverse_order order); |
|
1438 |
void neg_arguments(THD *thd); |
|
212.2.2
by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE |
1439 |
enum_field_types field_type() const { return DRIZZLE_TYPE_LONGLONG; } |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
1440 |
bool subst_argument_checker(uchar **arg __attribute__((unused))) |
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
1441 |
{ return true; } |
1
by brian
clean slate |
1442 |
Item *compile(Item_analyzer analyzer, uchar **arg_p, |
1443 |
Item_transformer transformer, uchar *arg_t); |
|
1444 |
};
|
|
1445 |
||
1446 |
||
1447 |
/*
|
|
1448 |
The class Item_equal is used to represent conjunctions of equality
|
|
1449 |
predicates of the form field1 = field2, and field=const in where
|
|
1450 |
conditions and on expressions.
|
|
1451 |
||
1452 |
All equality predicates of the form field1=field2 contained in a
|
|
1453 |
conjunction are substituted for a sequence of items of this class.
|
|
1454 |
An item of this class Item_equal(f1,f2,...fk) represents a
|
|
1455 |
multiple equality f1=f2=...=fk.
|
|
1456 |
||
1457 |
If a conjunction contains predicates f1=f2 and f2=f3, a new item of
|
|
1458 |
this class is created Item_equal(f1,f2,f3) representing the multiple
|
|
1459 |
equality f1=f2=f3 that substitutes the above equality predicates in
|
|
1460 |
the conjunction.
|
|
1461 |
A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be
|
|
1462 |
substituted for the item representing the same multiple equality
|
|
1463 |
f1=f2=f3.
|
|
1464 |
An item Item_equal(f1,f2) can appear instead of a conjunction of
|
|
1465 |
f2=f1 and f1=f2, or instead of just the predicate f1=f2.
|
|
1466 |
||
1467 |
An item of the class Item_equal inherits equalities from outer
|
|
1468 |
conjunctive levels.
|
|
1469 |
||
1470 |
Suppose we have a where condition of the following form:
|
|
1471 |
WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)).
|
|
1472 |
In this case:
|
|
1473 |
f1=f2 will be substituted for Item_equal(f1,f2);
|
|
1474 |
f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5);
|
|
1475 |
f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5);
|
|
1476 |
||
1477 |
An object of the class Item_equal can contain an optional constant
|
|
1478 |
item c. Then it represents a multiple equality of the form
|
|
1479 |
c=f1=...=fk.
|
|
1480 |
||
1481 |
Objects of the class Item_equal are used for the following:
|
|
1482 |
||
1483 |
1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any
|
|
1484 |
pair of tables ti and tj as joined by an equi-condition.
|
|
1485 |
Thus it provide us with additional access paths from table to table.
|
|
1486 |
||
1487 |
2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new
|
|
1488 |
SARGable predicates:
|
|
1489 |
f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj).
|
|
1490 |
It also can give us additional index scans and can allow us to
|
|
1491 |
improve selectivity estimates.
|
|
1492 |
||
1493 |
3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the
|
|
1494 |
selected execution plan for the query: if table ti is accessed
|
|
1495 |
before the table tj then in any predicate P in the where condition
|
|
1496 |
the occurrence of tj.fj is substituted for ti.fi. This can allow
|
|
1497 |
an evaluation of the predicate at an earlier step.
|
|
1498 |
||
1499 |
When feature 1 is supported they say that join transitive closure
|
|
1500 |
is employed.
|
|
1501 |
When feature 2 is supported they say that search argument transitive
|
|
1502 |
closure is employed.
|
|
1503 |
Both features are usually supported by preprocessing original query and
|
|
1504 |
adding additional predicates.
|
|
1505 |
We do not just add predicates, we rather dynamically replace some
|
|
1506 |
predicates that can not be used to access tables in the investigated
|
|
1507 |
plan for those, obtained by substitution of some fields for equal fields,
|
|
1508 |
that can be used.
|
|
1509 |
||
1510 |
Prepared Statements/Stored Procedures note: instances of class
|
|
1511 |
Item_equal are created only at the time a PS/SP is executed and
|
|
1512 |
are deleted in the end of execution. All changes made to these
|
|
1513 |
objects need not be registered in the list of changes of the parse
|
|
1514 |
tree and do not harm PS/SP re-execution.
|
|
1515 |
||
1516 |
Item equal objects are employed only at the optimize phase. Usually they are
|
|
1517 |
not supposed to be evaluated. Yet in some cases we call the method val_int()
|
|
1518 |
for them. We have to take care of restricting the predicate such an
|
|
1519 |
object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik.
|
|
1520 |
*/
|
|
1521 |
||
1522 |
class Item_equal: public Item_bool_func |
|
1523 |
{
|
|
1524 |
List<Item_field> fields; /* list of equal field items */ |
|
1525 |
Item *const_item; /* optional constant item equal to fields items */ |
|
1526 |
cmp_item *eval_item; |
|
1527 |
bool cond_false; |
|
1528 |
public: |
|
1529 |
inline Item_equal() |
|
1530 |
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0) |
|
1531 |
{ const_item_cache=0 ;} |
|
1532 |
Item_equal(Item_field *f1, Item_field *f2); |
|
1533 |
Item_equal(Item *c, Item_field *f); |
|
1534 |
Item_equal(Item_equal *item_equal); |
|
1535 |
inline Item* get_const() { return const_item; } |
|
1536 |
void add(Item *c); |
|
1537 |
void add(Item_field *f); |
|
1538 |
uint members(); |
|
1539 |
bool contains(Field *field); |
|
1540 |
Item_field* get_first() { return fields.head(); } |
|
1541 |
void merge(Item_equal *item); |
|
1542 |
void update_const(); |
|
1543 |
enum Functype functype() const { return MULT_EQUAL_FUNC; } |
|
152
by Brian Aker
longlong replacement |
1544 |
int64_t val_int(); |
1
by brian
clean slate |
1545 |
const char *func_name() const { return "multiple equal"; } |
1546 |
optimize_type select_optimize() const { return OPTIMIZE_EQUAL; } |
|
1547 |
void sort(Item_field_cmpfunc cmp, void *arg); |
|
1548 |
friend class Item_equal_iterator; |
|
1549 |
void fix_length_and_dec(); |
|
1550 |
bool fix_fields(THD *thd, Item **ref); |
|
1551 |
void update_used_tables(); |
|
1552 |
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); |
|
1553 |
Item *transform(Item_transformer transformer, uchar *arg); |
|
1554 |
virtual void print(String *str, enum_query_type query_type); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1555 |
const CHARSET_INFO *compare_collation() |
1
by brian
clean slate |
1556 |
{ return fields.head()->collation.collation; } |
1557 |
};
|
|
1558 |
||
1559 |
class COND_EQUAL: public Sql_alloc |
|
1560 |
{
|
|
1561 |
public: |
|
1562 |
uint max_members; /* max number of members the current level |
|
1563 |
list and all lower level lists */
|
|
1564 |
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */ |
|
1565 |
List<Item_equal> current_level; /* list of multiple equalities of |
|
1566 |
the current and level */
|
|
1567 |
COND_EQUAL() |
|
1568 |
{
|
|
1569 |
upper_levels= 0; |
|
1570 |
}
|
|
1571 |
};
|
|
1572 |
||
1573 |
||
1574 |
class Item_equal_iterator : public List_iterator_fast<Item_field> |
|
1575 |
{
|
|
1576 |
public: |
|
1577 |
inline Item_equal_iterator(Item_equal &item_equal) |
|
1578 |
:List_iterator_fast<Item_field> (item_equal.fields) |
|
1579 |
{}
|
|
1580 |
inline Item_field* operator++(int) |
|
1581 |
{
|
|
1582 |
Item_field *item= (*(List_iterator_fast<Item_field> *) this)++; |
|
1583 |
return item; |
|
1584 |
}
|
|
1585 |
inline void rewind(void) |
|
1586 |
{
|
|
1587 |
List_iterator_fast<Item_field>::rewind(); |
|
1588 |
}
|
|
1589 |
};
|
|
1590 |
||
1591 |
class Item_cond_and :public Item_cond |
|
1592 |
{
|
|
1593 |
public: |
|
1594 |
COND_EQUAL cond_equal; /* contains list of Item_equal objects for |
|
1595 |
the current and level and reference
|
|
1596 |
to multiple equalities of upper and levels */
|
|
1597 |
Item_cond_and() :Item_cond() {} |
|
1598 |
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {} |
|
1599 |
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {} |
|
1600 |
Item_cond_and(List<Item> &list_arg): Item_cond(list_arg) {} |
|
1601 |
enum Functype functype() const { return COND_AND_FUNC; } |
|
152
by Brian Aker
longlong replacement |
1602 |
int64_t val_int(); |
1
by brian
clean slate |
1603 |
const char *func_name() const { return "and"; } |
1604 |
table_map not_null_tables() const |
|
1605 |
{ return abort_on_null ? not_null_tables_cache: and_tables_cache; } |
|
1606 |
Item* copy_andor_structure(THD *thd) |
|
1607 |
{
|
|
1608 |
Item_cond_and *item; |
|
1609 |
if ((item= new Item_cond_and(thd, this))) |
|
1610 |
item->copy_andor_arguments(thd, this); |
|
1611 |
return item; |
|
1612 |
}
|
|
1613 |
Item *neg_transformer(THD *thd); |
|
1614 |
};
|
|
1615 |
||
1616 |
inline bool is_cond_and(Item *item) |
|
1617 |
{
|
|
1618 |
if (item->type() != Item::COND_ITEM) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
1619 |
return false; |
1
by brian
clean slate |
1620 |
|
1621 |
Item_cond *cond_item= (Item_cond*) item; |
|
1622 |
return (cond_item->functype() == Item_func::COND_AND_FUNC); |
|
1623 |
}
|
|
1624 |
||
1625 |
class Item_cond_or :public Item_cond |
|
1626 |
{
|
|
1627 |
public: |
|
1628 |
Item_cond_or() :Item_cond() {} |
|
1629 |
Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {} |
|
1630 |
Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {} |
|
1631 |
Item_cond_or(List<Item> &list_arg): Item_cond(list_arg) {} |
|
1632 |
enum Functype functype() const { return COND_OR_FUNC; } |
|
152
by Brian Aker
longlong replacement |
1633 |
int64_t val_int(); |
1
by brian
clean slate |
1634 |
const char *func_name() const { return "or"; } |
1635 |
table_map not_null_tables() const { return and_tables_cache; } |
|
1636 |
Item* copy_andor_structure(THD *thd) |
|
1637 |
{
|
|
1638 |
Item_cond_or *item; |
|
1639 |
if ((item= new Item_cond_or(thd, this))) |
|
1640 |
item->copy_andor_arguments(thd, this); |
|
1641 |
return item; |
|
1642 |
}
|
|
1643 |
Item *neg_transformer(THD *thd); |
|
1644 |
};
|
|
1645 |
||
1646 |
inline bool is_cond_or(Item *item) |
|
1647 |
{
|
|
1648 |
if (item->type() != Item::COND_ITEM) |
|
51.1.77
by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols |
1649 |
return false; |
1
by brian
clean slate |
1650 |
|
1651 |
Item_cond *cond_item= (Item_cond*) item; |
|
1652 |
return (cond_item->functype() == Item_func::COND_OR_FUNC); |
|
1653 |
}
|
|
1654 |
||
1655 |
/*
|
|
1656 |
XOR is Item_cond, not an Item_int_func because we could like to
|
|
1657 |
optimize (a XOR b) later on. It's low prio, though
|
|
1658 |
*/
|
|
1659 |
||
1660 |
class Item_cond_xor :public Item_cond |
|
1661 |
{
|
|
1662 |
public: |
|
1663 |
Item_cond_xor() :Item_cond() {} |
|
1664 |
Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {} |
|
1665 |
enum Functype functype() const { return COND_XOR_FUNC; } |
|
1666 |
/* TODO: remove the next line when implementing XOR optimization */
|
|
1667 |
enum Type type() const { return FUNC_ITEM; } |
|
152
by Brian Aker
longlong replacement |
1668 |
int64_t val_int(); |
1
by brian
clean slate |
1669 |
const char *func_name() const { return "xor"; } |
1670 |
void top_level_item() {} |
|
1671 |
};
|
|
1672 |
||
1673 |
||
1674 |
/* Some useful inline functions */
|
|
1675 |
||
1676 |
inline Item *and_conds(Item *a, Item *b) |
|
1677 |
{
|
|
1678 |
if (!b) return a; |
|
1679 |
if (!a) return b; |
|
1680 |
return new Item_cond_and(a, b); |
|
1681 |
}
|
|
1682 |
||
1683 |
Item *and_expressions(Item *a, Item *b, Item **org_item); |