21
21
This file defines all compare functions
25
#include "drizzled/sql_select.h"
26
#include "drizzled/error.h"
27
#include "drizzled/temporal.h"
28
#include "drizzled/item/cmpfunc.h"
29
#include "drizzled/cached_item.h"
30
#include "drizzled/item/cache_int.h"
31
#include "drizzled/item/int_with_ref.h"
32
#include "drizzled/check_stack_overrun.h"
33
#include "drizzled/time_functions.h"
34
#include "drizzled/internal/my_sys.h"
26
#include <drizzled/cached_item.h>
27
#include <drizzled/check_stack_overrun.h>
28
#include <drizzled/current_session.h>
29
#include <drizzled/error.h>
30
#include <drizzled/internal/my_sys.h>
31
#include <drizzled/item/cache_int.h>
32
#include <drizzled/item/cmpfunc.h>
33
#include <drizzled/item/int_with_ref.h>
34
#include <drizzled/item/subselect.h>
35
#include <drizzled/session.h>
36
#include <drizzled/sql_select.h>
37
#include <drizzled/temporal.h>
38
#include <drizzled/time_functions.h>
39
#include <drizzled/sql_lex.h>
40
#include <drizzled/system_variables.h>
36
43
#include <algorithm>
38
45
using namespace std;
43
49
extern const double log_10[309];
342
348
higher than the precedence of NOT.
345
void Item_func_not::print(String *str, enum_query_type query_type)
351
void Item_func_not::print(String *str)
347
353
str->append('(');
348
Item_func::print(str, query_type);
354
Item_func::print(str);
349
355
str->append(')');
377
383
(test_sub_item && !test_sub_item->any_value()));
380
void Item_func_not_all::print(String *str, enum_query_type query_type)
386
void Item_func_not_all::print(String *str)
383
Item_func::print(str, query_type);
389
Item_func::print(str);
385
args[0]->print(str, query_type);
472
478
Item *tmp= new Item_int_with_ref(field->val_int(), *item,
473
479
test(field->flags & UNSIGNED_FLAG));
475
session->change_item_tree(item, tmp);
476
482
result= 1; // Item was replaced
576
Arg_comparator::Arg_comparator():
577
session(current_session),
582
Arg_comparator::Arg_comparator(Item **a1, Item **a2):
585
session(current_session),
571
590
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
841
858
return CMP_DATE_DFLT;
843
if (! temporal.from_string(str_val->c_ptr(), str_val->length()))
845
/* Chuck an error. Bad datetime input. */
846
my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), str_val->c_ptr());
847
return CMP_DATE_DFLT; /* :( What else can I return... */
850
/* String conversion was good. Convert to an integer for comparison purposes. */
851
temporal.to_int64_t(&value);
860
if (temporal.from_string(str_val->c_ptr(), str_val->length()))
862
/* String conversion was good. Convert to an integer for comparison purposes. */
863
temporal.to_int64_t(&value);
867
/* We aren't a DATETIME but still could be a TIME */
869
if (timevalue.from_string(str_val->c_ptr(), str_val->length()))
872
timevalue.to_uint64_t(timeint);
873
value= static_cast<int64_t>(timeint);
877
/* Chuck an error. Bad datetime input. */
878
my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), str_val->c_ptr());
879
return CMP_DATE_DFLT; /* :( What else can I return... */
854
884
*const_value= value;
1430
void Item_func_truth::print(String *str, enum_query_type query_type)
1460
void Item_func_truth::print(String *str)
1432
1462
str->append('(');
1433
args[0]->print(str, query_type);
1463
args[0]->print(str);
1434
1464
str->append(STRING_WITH_LEN(" is "));
1435
1465
if (! affirmative)
1436
1466
str->append(STRING_WITH_LEN("not "));
1659
1689
new_item= (*args)->transform(transformer, argument);
1663
Session::change_item_tree() should be called only if the tree was
1664
really transformed, i.e. when a new item has been created.
1665
Otherwise we'll be allocating a lot of unnecessary memory for
1666
change records at each execution.
1668
if ((*args) != new_item)
1669
getSession().change_item_tree(args, new_item);
1672
1695
Transform the right IN operand which should be an Item_in_subselect or a
1979
2002
if (Item_func_opt_neg::fix_fields(session, ref))
1982
session->lex->current_select->between_count++;
2005
session->lex().current_select->between_count++;
1984
2007
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
1985
2008
if (pred_level && !negated)
2168
void Item_func_between::print(String *str, enum_query_type query_type)
2191
void Item_func_between::print(String *str)
2170
2193
str->append('(');
2171
args[0]->print(str, query_type);
2194
args[0]->print(str);
2173
2196
str->append(STRING_WITH_LEN(" not"));
2174
2197
str->append(STRING_WITH_LEN(" between "));
2175
args[1]->print(str, query_type);
2198
args[1]->print(str);
2176
2199
str->append(STRING_WITH_LEN(" and "));
2177
args[2]->print(str, query_type);
2200
args[2]->print(str);
2178
2201
str->append(')');
2823
2846
Fix this so that it prints the whole CASE expression
2826
void Item_func_case::print(String *str, enum_query_type query_type)
2849
void Item_func_case::print(String *str)
2828
2851
str->append(STRING_WITH_LEN("(case "));
2829
2852
if (first_expr_num != -1)
2831
args[first_expr_num]->print(str, query_type);
2854
args[first_expr_num]->print(str);
2832
2855
str->append(' ');
2834
2857
for (uint32_t i=0 ; i < ncases ; i+=2)
2836
2859
str->append(STRING_WITH_LEN("when "));
2837
args[i]->print(str, query_type);
2860
args[i]->print(str);
2838
2861
str->append(STRING_WITH_LEN(" then "));
2839
args[i+1]->print(str, query_type);
2862
args[i+1]->print(str);
2840
2863
str->append(' ');
2842
2865
if (else_expr_num != -1)
2844
2867
str->append(STRING_WITH_LEN("else "));
2845
args[else_expr_num]->print(str, query_type);
2868
args[else_expr_num]->print(str);
2846
2869
str->append(' ');
2848
2871
str->append(STRING_WITH_LEN("end)"));
3102
3125
return (int) ((*compare)(collation, base+start*size, result) == 0);
3105
in_string::in_string(uint32_t elements,qsort2_cmp cmp_func, const CHARSET_INFO * const cs)
3128
in_string::in_string(uint32_t elements,qsort2_cmp cmp_func, const charset_info_st * const cs)
3106
3129
:in_vector(elements, sizeof(String), cmp_func, cs),
3107
3130
tmp(buff, sizeof(buff), &my_charset_bin)
3199
3222
return (unsigned char*) &tmp;
3225
in_datetime::in_datetime(Item *warn_item_arg, uint32_t elements) :
3226
in_int64_t(elements),
3227
session(current_session),
3228
warn_item(warn_item_arg),
3202
3232
void in_datetime::set(uint32_t pos, Item *item)
3204
3234
Item **tmp_item= &item;
3540
static int srtcmp_in(const CHARSET_INFO * const cs, const String *x,const String *y)
3570
static int srtcmp_in(const charset_info_st * const cs, const String *x,const String *y)
3542
3572
return cs->coll->strnncollsp(cs,
3543
3573
(unsigned char *) x->ptr(),x->length(),
3779
void Item_func_in::print(String *str, enum_query_type query_type)
3809
void Item_func_in::print(String *str)
3781
3811
str->append('(');
3782
args[0]->print(str, query_type);
3812
args[0]->print(str);
3784
3814
str->append(STRING_WITH_LEN(" not"));
3785
3815
str->append(STRING_WITH_LEN(" in ("));
3786
print_args(str, 1, query_type);
3787
3817
str->append(STRING_WITH_LEN("))"));
3862
3892
void Item_cond::copy_andor_arguments(Session *session, Item_cond *item)
3864
List_iterator_fast<Item> li(item->list);
3894
List<Item>::iterator li(item->list.begin());
3865
3895
while (Item *it= li++)
3866
3896
list.push_back(it->copy_andor_structure(session));
3871
3901
Item_cond::fix_fields(Session *session, Item **)
3873
3903
assert(fixed == 0);
3874
List_iterator<Item> li(list);
3904
List<Item>::iterator li(list.begin());
3876
3906
void *orig_session_marker= session->session_marker;
3877
3907
unsigned char buff[sizeof(char*)]; // Max local vars in function
3911
3941
!((Item_cond*) item)->list.is_empty())
3912
3942
{ // Identical function
3913
3943
li.replace(((Item_cond*) item)->list);
3914
((Item_cond*) item)->list.empty();
3915
item= *li.ref(); // new current item
3944
((Item_cond*) item)->list.clear();
3945
item= &*li; // new current item
3917
3947
if (abort_on_null)
3918
3948
item->top_level_item();
3920
3950
// item can be substituted in fix_fields
3921
3951
if ((!item->fixed &&
3922
3952
item->fix_fields(session, li.ref())) ||
3923
(item= *li.ref())->check_cols(1))
3953
(item= &*li)->check_cols(1))
3925
3955
used_tables_cache|= item->used_tables();
3926
3956
if (item->const_item())
3980
4010
bool Item_cond::walk(Item_processor processor, bool walk_subquery, unsigned char *arg)
3982
List_iterator_fast<Item> li(list);
4012
List<Item>::iterator li(list.begin());
3984
4014
while ((item= li++))
3985
4015
if (item->walk(processor, walk_subquery, arg))
4009
4039
Item *Item_cond::transform(Item_transformer transformer, unsigned char *arg)
4011
List_iterator<Item> li(list);
4041
List<Item>::iterator li(list.begin());
4013
4043
while ((item= li++))
4015
4045
Item *new_item= item->transform(transformer, arg);
4020
Session::change_item_tree() should be called only if the tree was
4021
really transformed, i.e. when a new item has been created.
4022
Otherwise we'll be allocating a lot of unnecessary memory for
4023
change records at each execution.
4025
if (new_item != item)
4026
getSession().change_item_tree(li.ref(), new_item);
4048
*li.ref()= new_item;
4028
4050
return Item_func::transform(transformer, arg);
4078
4100
void Item_cond::traverse_cond(Cond_traverser traverser,
4079
4101
void *arg, traverse_order order)
4081
List_iterator<Item> li(list);
4103
List<Item>::iterator li(list.begin());
4084
4106
switch (order) {
4116
4138
that have or refer (HAVING) to a SUM expression.
4119
void Item_cond::split_sum_func(Session *session, Item **ref_pointer_array,
4141
void Item_cond::split_sum_func(Session *session, Item **ref_pointer_array, List<Item> &fields)
4122
List_iterator<Item> li(list);
4143
List<Item>::iterator li(list.begin());
4124
4145
while ((item= li++))
4125
item->split_sum_func(session, ref_pointer_array,
4126
fields, li.ref(), true);
4146
item->split_sum_func(session, ref_pointer_array, fields, li.ref(), true);
4153
void Item_cond::print(String *str, enum_query_type query_type)
4173
void Item_cond::print(String *str)
4155
4175
str->append('(');
4156
List_iterator_fast<Item> li(list);
4176
List<Item>::iterator li(list.begin());
4158
4178
if ((item=li++))
4159
item->print(str, query_type);
4160
4180
while ((item=li++))
4162
4182
str->append(' ');
4163
4183
str->append(func_name());
4164
4184
str->append(' ');
4165
item->print(str, query_type);
4167
4187
str->append(')');
4279
if (((Item_cond_and*) a)->add((Item*) b))
4299
((Item_cond_and*) a)->add((Item*) b);
4281
4300
((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
4282
4301
((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables();
4345
void Item_func_isnotnull::print(String *str, enum_query_type query_type)
4364
void Item_func_isnotnull::print(String *str)
4347
4366
str->append('(');
4348
args[0]->print(str, query_type);
4367
args[0]->print(str);
4349
4368
str->append(STRING_WITH_LEN(" is not null)"));
4599
4618
int *end = bmBc + alphabet_size;
4601
4620
const int plm1 = pattern_len - 1;
4602
const CHARSET_INFO *const cs= cmp.cmp_collation.collation;
4621
const charset_info_st *const cs= cmp.cmp_collation.collation;
4604
4623
for (i = bmBc; i < end; i++)
4605
4624
*i = pattern_len;
4627
4646
bool Item_func_like::turboBM_matches(const char* text, int text_len) const
4629
register int bcShift;
4630
register int turboShift;
4631
4650
int shift = pattern_len;
4634
const CHARSET_INFO * const cs= cmp.cmp_collation.collation;
4653
const charset_info_st * const cs= cmp.cmp_collation.collation;
4636
4655
const int plm1= pattern_len - 1;
4637
4656
const int tlmpl= text_len - pattern_len;
5071
5090
bool Item_equal::fix_fields(Session *, Item **)
5073
List_iterator_fast<Item_field> li(fields);
5092
List<Item_field>::iterator li(fields.begin());
5075
5094
not_null_tables_cache= used_tables_cache= 0;
5076
5095
const_item_cache= false;
5091
5110
void Item_equal::update_used_tables()
5093
List_iterator_fast<Item_field> li(fields);
5112
List<Item_field>::iterator li(fields.begin());
5095
5114
not_null_tables_cache= used_tables_cache= 0;
5096
5115
if ((const_item_cache= cond_false))
5108
5127
Item_field *item_field;
5109
5128
if (cond_false)
5111
List_iterator_fast<Item_field> it(fields);
5130
List<Item_field>::iterator it(fields.begin());
5112
5131
Item *item= const_item ? const_item : it++;
5113
5132
eval_item->store_value(item);
5114
5133
if ((null_value= item->null_value))
5147
5166
Item *Item_equal::transform(Item_transformer transformer, unsigned char *arg)
5149
List_iterator<Item_field> it(fields);
5168
List<Item_field>::iterator it(fields.begin());
5151
5170
while ((item= it++))
5153
5172
Item *new_item= item->transform(transformer, arg);
5158
Session::change_item_tree() should be called only if the tree was
5159
really transformed, i.e. when a new item has been created.
5160
Otherwise we'll be allocating a lot of unnecessary memory for
5161
change records at each execution.
5163
if (new_item != item)
5164
getSession().change_item_tree((Item **) it.ref(), new_item);
5175
*(Item **)it.ref()= new_item;
5166
5177
return Item_func::transform(transformer, arg);
5169
void Item_equal::print(String *str, enum_query_type query_type)
5180
void Item_equal::print(String *str)
5171
5182
str->append(func_name());
5172
5183
str->append('(');
5173
List_iterator_fast<Item_field> it(fields);
5184
List<Item_field>::iterator it(fields.begin());
5175
5186
if (const_item)
5176
const_item->print(str, query_type);
5187
const_item->print(str);
5180
item->print(str, query_type);
5182
5193
while ((item= it++))
5184
5195
str->append(',');
5185
5196
str->append(' ');
5186
item->print(str, query_type);
5188
5199
str->append(')');
5202
cmp_item_datetime::cmp_item_datetime(Item *warn_item_arg) :
5203
session(current_session),
5204
warn_item(warn_item_arg),
5191
5208
} /* namespace drizzled */