2009-09-23 23:32:31 +02:00
|
|
|
#ifndef ITEM_CMPFUNC_INCLUDED
|
|
|
|
#define ITEM_CMPFUNC_INCLUDED
|
|
|
|
|
2012-02-16 10:48:16 +01:00
|
|
|
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
|
|
|
|
/* compare and test functions */
|
|
|
|
|
2005-05-04 15:05:56 +02:00
|
|
|
#ifdef USE_PRAGMA_INTERFACE
|
2000-07-31 21:29:14 +02:00
|
|
|
#pragma interface /* gcc class implementation */
|
|
|
|
#endif
|
|
|
|
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "thr_malloc.h" /* sql_calloc */
|
|
|
|
#include "item_func.h" /* Item_int_func, Item_bool_func */
|
2010-07-23 22:16:29 +02:00
|
|
|
#include "my_regex.h"
|
2010-03-31 16:05:33 +02:00
|
|
|
|
2002-12-04 10:01:48 +01:00
|
|
|
extern Item_result item_cmp_type(Item_result a,Item_result b);
|
|
|
|
class Item_bool_func2;
|
|
|
|
class Arg_comparator;
|
|
|
|
|
|
|
|
typedef int (Arg_comparator::*arg_cmp_func)();
|
|
|
|
|
2004-02-19 07:21:37 +01:00
|
|
|
typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg);
|
|
|
|
|
2002-12-04 10:01:48 +01:00
|
|
|
class Arg_comparator: public Sql_alloc
|
|
|
|
{
|
|
|
|
Item **a, **b;
|
|
|
|
arg_cmp_func func;
|
2009-11-17 15:06:46 +01:00
|
|
|
Item_result_field *owner;
|
2002-12-04 10:01:48 +01:00
|
|
|
Arg_comparator *comparators; // used only for compare_row()
|
2007-01-31 06:51:05 +01:00
|
|
|
double precision;
|
2007-04-26 22:12:09 +02:00
|
|
|
/* Fields used in DATE/DATETIME comparison. */
|
|
|
|
THD *thd;
|
|
|
|
enum_field_types a_type, b_type; // Types of a and b items
|
|
|
|
Item *a_cache, *b_cache; // Cached values of a and b items
|
|
|
|
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC
|
2009-11-17 15:06:46 +01:00
|
|
|
bool set_null; // TRUE <=> set owner->null_value
|
|
|
|
// when one of arguments is NULL.
|
2007-04-26 22:12:09 +02:00
|
|
|
enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE,
|
|
|
|
CMP_DATE_WITH_STR, CMP_STR_WITH_DATE };
|
2009-11-17 15:06:46 +01:00
|
|
|
longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg,
|
|
|
|
Item *warn_item, bool *is_null);
|
|
|
|
longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg,
|
|
|
|
Item *warn_item, bool *is_null);
|
2009-12-10 07:05:44 +01:00
|
|
|
bool try_year_cmp_func(Item_result type);
|
2002-12-04 10:01:48 +01:00
|
|
|
public:
|
2003-07-03 14:00:01 +02:00
|
|
|
DTCollation cmp_collation;
|
2009-11-17 15:06:46 +01:00
|
|
|
/* Allow owner function to use string buffers. */
|
|
|
|
String value1, value2;
|
2003-07-03 14:00:01 +02:00
|
|
|
|
2010-04-16 13:42:34 +02:00
|
|
|
Arg_comparator(): comparators(0), thd(0), a_cache(0), b_cache(0), set_null(TRUE),
|
2009-12-10 07:05:44 +01:00
|
|
|
get_value_a_func(0), get_value_b_func(0) {};
|
2010-04-16 13:42:34 +02:00
|
|
|
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), comparators(0), thd(0),
|
2009-12-15 18:08:21 +01:00
|
|
|
a_cache(0), b_cache(0), set_null(TRUE),
|
2009-11-17 15:06:46 +01:00
|
|
|
get_value_a_func(0), get_value_b_func(0) {};
|
2002-12-04 10:01:48 +01:00
|
|
|
|
2009-11-17 15:06:46 +01:00
|
|
|
int set_compare_func(Item_result_field *owner, Item_result type);
|
|
|
|
inline int set_compare_func(Item_result_field *owner_arg)
|
2002-12-04 10:01:48 +01:00
|
|
|
{
|
2003-11-28 11:18:13 +01:00
|
|
|
return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
|
2006-06-14 23:48:41 +02:00
|
|
|
(*b)->result_type()));
|
2002-12-04 10:01:48 +01:00
|
|
|
}
|
2009-11-17 15:06:46 +01:00
|
|
|
int set_cmp_func(Item_result_field *owner_arg,
|
2002-12-04 10:01:48 +01:00
|
|
|
Item **a1, Item **a2,
|
2007-04-26 22:12:09 +02:00
|
|
|
Item_result type);
|
|
|
|
|
2009-11-17 15:06:46 +01:00
|
|
|
inline int set_cmp_func(Item_result_field *owner_arg,
|
|
|
|
Item **a1, Item **a2, bool set_null_arg)
|
2002-12-04 10:01:48 +01:00
|
|
|
{
|
2009-11-17 15:06:46 +01:00
|
|
|
set_null= set_null_arg;
|
2006-06-14 23:48:41 +02:00
|
|
|
return set_cmp_func(owner_arg, a1, a2,
|
|
|
|
item_cmp_type((*a1)->result_type(),
|
|
|
|
(*a2)->result_type()));
|
2002-12-04 10:01:48 +01:00
|
|
|
}
|
|
|
|
inline int compare() { return (this->*func)(); }
|
|
|
|
|
|
|
|
int compare_string(); // compare args[0] & args[1]
|
2004-02-16 09:03:25 +01:00
|
|
|
int compare_binary_string(); // compare args[0] & args[1]
|
2002-12-04 10:01:48 +01:00
|
|
|
int compare_real(); // compare args[0] & args[1]
|
2005-02-08 23:50:45 +01:00
|
|
|
int compare_decimal(); // compare args[0] & args[1]
|
2004-08-18 00:37:31 +02:00
|
|
|
int compare_int_signed(); // compare args[0] & args[1]
|
2004-08-11 21:08:20 +02:00
|
|
|
int compare_int_signed_unsigned();
|
|
|
|
int compare_int_unsigned_signed();
|
|
|
|
int compare_int_unsigned();
|
2002-12-04 10:01:48 +01:00
|
|
|
int compare_row(); // compare args[0] & args[1]
|
|
|
|
int compare_e_string(); // compare args[0] & args[1]
|
2004-02-16 09:03:25 +01:00
|
|
|
int compare_e_binary_string(); // compare args[0] & args[1]
|
2002-12-04 10:01:48 +01:00
|
|
|
int compare_e_real(); // compare args[0] & args[1]
|
2005-02-08 23:50:45 +01:00
|
|
|
int compare_e_decimal(); // compare args[0] & args[1]
|
2002-12-04 10:01:48 +01:00
|
|
|
int compare_e_int(); // compare args[0] & args[1]
|
2004-08-17 00:59:24 +02:00
|
|
|
int compare_e_int_diff_signedness();
|
2002-12-04 10:01:48 +01:00
|
|
|
int compare_e_row(); // compare args[0] & args[1]
|
2007-01-31 06:51:05 +01:00
|
|
|
int compare_real_fixed();
|
|
|
|
int compare_e_real_fixed();
|
2007-04-26 22:12:09 +02:00
|
|
|
int compare_datetime(); // compare args[0] & args[1] as DATETIMEs
|
|
|
|
|
|
|
|
static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b,
|
|
|
|
ulonglong *const_val_arg);
|
2002-12-04 10:01:48 +01:00
|
|
|
|
2009-11-06 20:34:25 +01:00
|
|
|
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
|
|
|
|
Item_result type);
|
2009-11-17 15:06:46 +01:00
|
|
|
void set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1);
|
2005-02-08 23:50:45 +01:00
|
|
|
static arg_cmp_func comparator_matrix [5][2];
|
2009-11-17 15:06:46 +01:00
|
|
|
inline bool is_owner_equal_func()
|
|
|
|
{
|
|
|
|
return (owner->type() == Item::FUNC_ITEM &&
|
|
|
|
((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC);
|
|
|
|
}
|
2010-04-16 13:42:34 +02:00
|
|
|
void cleanup()
|
|
|
|
{
|
|
|
|
delete [] comparators;
|
|
|
|
comparators= 0;
|
|
|
|
}
|
2010-07-19 19:11:47 +02:00
|
|
|
/*
|
|
|
|
Set correct cmp_context if items would be compared as INTs.
|
|
|
|
*/
|
|
|
|
inline void set_cmp_context_for_datetime()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(func == &Arg_comparator::compare_datetime);
|
|
|
|
if ((*a)->result_as_longlong())
|
|
|
|
(*a)->cmp_context= INT_RESULT;
|
|
|
|
if ((*b)->result_as_longlong())
|
|
|
|
(*b)->cmp_context= INT_RESULT;
|
|
|
|
}
|
2002-12-04 10:01:48 +01:00
|
|
|
friend class Item_func;
|
|
|
|
};
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_bool_func :public Item_int_func
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_bool_func() :Item_int_func() {}
|
|
|
|
Item_bool_func(Item *a) :Item_int_func(a) {}
|
|
|
|
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
|
2004-01-19 16:53:25 +01:00
|
|
|
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
|
2004-08-31 20:10:57 +02:00
|
|
|
bool is_bool_func() { return 1; }
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec() { decimals=0; max_length=1; }
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return 1; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
Bug#24532 (The return data type of IS TRUE is different from similar
operations)
Before this change, the boolean predicates:
- X IS TRUE,
- X IS NOT TRUE,
- X IS FALSE,
- X IS NOT FALSE
were implemented by expanding the Item tree in the parser, by using a
construct like:
Item_func_if(Item_func_ifnull(X, <value>), <value>, <value>)
Each <value> was a constant integer, either 0 or 1.
A bug in the implementation of the function IF(a, b, c), in
Item_func_if::fix_length_and_dec(), would cause the following :
When the arguments b and c are both unsigned, the result type of the
function was signed, instead of unsigned.
When the result of the if function is signed, space for the sign could be
counted twice (in the max() expression for a signed argument, and in the
total), causing the member max_length to be too high.
An effect of this is that the final type of IF(x, int(1), int(1)) would be
int(2) instead of int(1).
With this fix, the problems found in Item_func_if::fix_length_and_dec()
have been fixed.
While it's semantically correct to represent 'X IS TRUE' with
Item_func_if(Item_func_ifnull(X, <value>), <value>, <value>),
there are however more problems with this construct.
a)
Building the parse tree involves :
- creating 5 Item instances (3 ints, 1 ifnull, 1 if),
- creating each Item calls my_pthread_getspecific_ptr() once in the operator
new(size), and a second time in the Item::Item() constructor, resulting
in a total of 10 calls to get the current thread.
Evaluating the expression involves evaluating up to 4 nodes at runtime.
This representation could be greatly simplified and improved.
b)
Transforming the parse tree internally with if(ifnull(...)) is fine as long
as this transformation is internal to the server implementation.
With views however, the result of the parse tree is later exposed by the
::print() functions, and stored as part of the view definition.
Doing this has long term consequences:
1)
The original semantic 'X IS TRUE' is lost, and replaced by the
if(ifnull(...)) expression. As a result, SHOW CREATE VIEW does not restore
the original code.
2)
Should a future version of MySQL implement the SQL BOOLEAN data type for
example, views created today using 'X IS NULL' can be exported using
mysqldump, and imported again. Such views would be converted correctly and
automatically to use a BOOLEAN column in the future version.
With 'X IS TRUE' and the current implementations, views using these
"boolean" predicates would not be converted during the export/import, and
would use integer columns instead.
The difference traces back to how SHOW CREATE VIEW preserves 'X IS NULL' but
does not preserve the 'X IS TRUE' semantic.
With this fix, internal representation of 'X IS TRUE' booleans predicates
has changed, so that:
- dedicated Item classes are created for each predicate,
- only 1 Item is created to represent 1 predicate
- my_pthread_getspecific_ptr() is invoked 1 time instead of 10
- SHOW CREATE VIEW preserves the original semantic, and prints 'X IS TRUE'.
Note that, because of the fix in Item_func_if, views created before this fix
will:
- correctly use a int(1) type instead of int(2) for boolean predicates,
- incorrectly print the if(ifnull(...), ...) expression in SHOW CREATE VIEW,
since the original semantic (X IS TRUE) has been lost.
- except for the syntax used in SHOW CREATE VIEW, these views will operate
properly, no action is needed.
Views created after this fix will operate correctly, and will preserve the
original code semantic in SHOW CREATE VIEW.
2007-02-12 21:59:29 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
Abstract Item class, to represent <code>X IS [NOT] (TRUE | FALSE)</code>
|
|
|
|
boolean predicates.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_truth : public Item_bool_func
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual bool val_bool();
|
|
|
|
virtual longlong val_int();
|
|
|
|
virtual void fix_length_and_dec();
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
Bug#24532 (The return data type of IS TRUE is different from similar
operations)
Before this change, the boolean predicates:
- X IS TRUE,
- X IS NOT TRUE,
- X IS FALSE,
- X IS NOT FALSE
were implemented by expanding the Item tree in the parser, by using a
construct like:
Item_func_if(Item_func_ifnull(X, <value>), <value>, <value>)
Each <value> was a constant integer, either 0 or 1.
A bug in the implementation of the function IF(a, b, c), in
Item_func_if::fix_length_and_dec(), would cause the following :
When the arguments b and c are both unsigned, the result type of the
function was signed, instead of unsigned.
When the result of the if function is signed, space for the sign could be
counted twice (in the max() expression for a signed argument, and in the
total), causing the member max_length to be too high.
An effect of this is that the final type of IF(x, int(1), int(1)) would be
int(2) instead of int(1).
With this fix, the problems found in Item_func_if::fix_length_and_dec()
have been fixed.
While it's semantically correct to represent 'X IS TRUE' with
Item_func_if(Item_func_ifnull(X, <value>), <value>, <value>),
there are however more problems with this construct.
a)
Building the parse tree involves :
- creating 5 Item instances (3 ints, 1 ifnull, 1 if),
- creating each Item calls my_pthread_getspecific_ptr() once in the operator
new(size), and a second time in the Item::Item() constructor, resulting
in a total of 10 calls to get the current thread.
Evaluating the expression involves evaluating up to 4 nodes at runtime.
This representation could be greatly simplified and improved.
b)
Transforming the parse tree internally with if(ifnull(...)) is fine as long
as this transformation is internal to the server implementation.
With views however, the result of the parse tree is later exposed by the
::print() functions, and stored as part of the view definition.
Doing this has long term consequences:
1)
The original semantic 'X IS TRUE' is lost, and replaced by the
if(ifnull(...)) expression. As a result, SHOW CREATE VIEW does not restore
the original code.
2)
Should a future version of MySQL implement the SQL BOOLEAN data type for
example, views created today using 'X IS NULL' can be exported using
mysqldump, and imported again. Such views would be converted correctly and
automatically to use a BOOLEAN column in the future version.
With 'X IS TRUE' and the current implementations, views using these
"boolean" predicates would not be converted during the export/import, and
would use integer columns instead.
The difference traces back to how SHOW CREATE VIEW preserves 'X IS NULL' but
does not preserve the 'X IS TRUE' semantic.
With this fix, internal representation of 'X IS TRUE' booleans predicates
has changed, so that:
- dedicated Item classes are created for each predicate,
- only 1 Item is created to represent 1 predicate
- my_pthread_getspecific_ptr() is invoked 1 time instead of 10
- SHOW CREATE VIEW preserves the original semantic, and prints 'X IS TRUE'.
Note that, because of the fix in Item_func_if, views created before this fix
will:
- correctly use a int(1) type instead of int(2) for boolean predicates,
- incorrectly print the if(ifnull(...), ...) expression in SHOW CREATE VIEW,
since the original semantic (X IS TRUE) has been lost.
- except for the syntax used in SHOW CREATE VIEW, these views will operate
properly, no action is needed.
Views created after this fix will operate correctly, and will preserve the
original code semantic in SHOW CREATE VIEW.
2007-02-12 21:59:29 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
Item_func_truth(Item *a, bool a_value, bool a_affirmative)
|
|
|
|
: Item_bool_func(a), value(a_value), affirmative(a_affirmative)
|
|
|
|
{}
|
|
|
|
|
|
|
|
~Item_func_truth()
|
|
|
|
{}
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
True for <code>X IS [NOT] TRUE</code>,
|
|
|
|
false for <code>X IS [NOT] FALSE</code> predicates.
|
|
|
|
*/
|
|
|
|
const bool value;
|
|
|
|
/**
|
|
|
|
True for <code>X IS Y</code>, false for <code>X IS NOT Y</code> predicates.
|
|
|
|
*/
|
|
|
|
const bool affirmative;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This Item represents a <code>X IS TRUE</code> boolean predicate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_istrue : public Item_func_truth
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_istrue(Item *a) : Item_func_truth(a, true, true) {}
|
|
|
|
~Item_func_istrue() {}
|
|
|
|
virtual const char* func_name() const { return "istrue"; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This Item represents a <code>X IS NOT TRUE</code> boolean predicate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_isnottrue : public Item_func_truth
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_isnottrue(Item *a) : Item_func_truth(a, true, false) {}
|
|
|
|
~Item_func_isnottrue() {}
|
|
|
|
virtual const char* func_name() const { return "isnottrue"; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This Item represents a <code>X IS FALSE</code> boolean predicate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_isfalse : public Item_func_truth
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_isfalse(Item *a) : Item_func_truth(a, false, true) {}
|
|
|
|
~Item_func_isfalse() {}
|
|
|
|
virtual const char* func_name() const { return "isfalse"; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
This Item represents a <code>X IS NOT FALSE</code> boolean predicate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_isnotfalse : public Item_func_truth
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_isnotfalse(Item *a) : Item_func_truth(a, false, false) {}
|
|
|
|
~Item_func_isnotfalse() {}
|
|
|
|
virtual const char* func_name() const { return "isnotfalse"; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-12-19 12:35:12 +01:00
|
|
|
class Item_cache;
|
2006-10-31 18:51:09 +01:00
|
|
|
#define UNKNOWN ((my_bool)-1)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Item_in_optimizer(left_expr, Item_in_subselect(...))
|
|
|
|
|
|
|
|
Item_in_optimizer is used to wrap an instance of Item_in_subselect. This
|
|
|
|
class does the following:
|
|
|
|
- Evaluate the left expression and store it in Item_cache_* object (to
|
|
|
|
avoid re-evaluating it many times during subquery execution)
|
|
|
|
- Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we
|
|
|
|
don't care if the result is NULL or FALSE.
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
It is not quite clear why the above listed functionality should be
|
|
|
|
placed into a separate class called 'Item_in_optimizer'.
|
|
|
|
*/
|
|
|
|
|
2002-12-06 20:55:53 +01:00
|
|
|
class Item_in_optimizer: public Item_bool_func
|
|
|
|
{
|
|
|
|
protected:
|
2002-12-19 12:35:12 +01:00
|
|
|
Item_cache *cache;
|
2004-02-12 02:10:26 +01:00
|
|
|
bool save_cache;
|
2006-10-31 18:51:09 +01:00
|
|
|
/*
|
|
|
|
Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries:
|
|
|
|
UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated
|
|
|
|
FALSE - result is FALSE
|
|
|
|
TRUE - result is NULL
|
|
|
|
*/
|
|
|
|
my_bool result_for_null_param;
|
2002-12-06 20:55:53 +01:00
|
|
|
public:
|
2002-12-19 20:15:09 +01:00
|
|
|
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
2010-07-23 22:16:29 +02:00
|
|
|
Item_bool_func(a, reinterpret_cast<Item *>(b)), cache(0),
|
2006-10-31 18:51:09 +01:00
|
|
|
save_cache(0), result_for_null_param(UNKNOWN)
|
2012-02-24 07:23:36 +01:00
|
|
|
{ with_subselect= true; }
|
2005-07-01 06:05:42 +02:00
|
|
|
bool fix_fields(THD *, Item **);
|
|
|
|
bool fix_left(THD *thd, Item **ref);
|
2002-12-19 12:35:12 +01:00
|
|
|
bool is_null();
|
2002-12-06 20:55:53 +01:00
|
|
|
longlong val_int();
|
2004-02-08 19:14:13 +01:00
|
|
|
void cleanup();
|
2003-10-12 16:56:05 +02:00
|
|
|
const char *func_name() const { return "<in_optimizer>"; }
|
2002-12-19 20:15:09 +01:00
|
|
|
Item_cache **get_cache() { return &cache; }
|
2004-02-12 02:10:26 +01:00
|
|
|
void keep_top_level_cache();
|
2002-12-06 20:55:53 +01:00
|
|
|
};
|
|
|
|
|
2003-11-03 11:28:36 +01:00
|
|
|
class Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Comp_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Comp_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const = 0;
|
|
|
|
virtual const char* symbol(bool invert) const = 0;
|
|
|
|
virtual bool eqne_op() const = 0;
|
|
|
|
virtual bool l_op() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Eq_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Eq_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Eq_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? "<>" : "="; }
|
|
|
|
virtual bool eqne_op() const { return 1; }
|
|
|
|
virtual bool l_op() const { return 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Ne_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Ne_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Ne_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? "=" : "<>"; }
|
|
|
|
virtual bool eqne_op() const { return 1; }
|
|
|
|
virtual bool l_op() const { return 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Gt_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Gt_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Gt_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? "<=" : ">"; }
|
|
|
|
virtual bool eqne_op() const { return 0; }
|
|
|
|
virtual bool l_op() const { return 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Lt_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Lt_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Lt_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? ">=" : "<"; }
|
|
|
|
virtual bool eqne_op() const { return 0; }
|
|
|
|
virtual bool l_op() const { return 1; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Ge_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Ge_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Ge_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? "<" : ">="; }
|
|
|
|
virtual bool eqne_op() const { return 0; }
|
|
|
|
virtual bool l_op() const { return 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class Le_creator :public Comp_creator
|
|
|
|
{
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
Le_creator() {} /* Remove gcc warning */
|
|
|
|
virtual ~Le_creator() {} /* Remove gcc warning */
|
2003-11-03 11:28:36 +01:00
|
|
|
virtual Item_bool_func2* create(Item *a, Item *b) const;
|
|
|
|
virtual const char* symbol(bool invert) const { return invert? ">" : "<="; }
|
|
|
|
virtual bool eqne_op() const { return 0; }
|
|
|
|
virtual bool l_op() const { return 1; }
|
|
|
|
};
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_bool_func2 :public Item_int_func
|
|
|
|
{ /* Bool with 2 string args */
|
|
|
|
protected:
|
2002-12-04 10:01:48 +01:00
|
|
|
Arg_comparator cmp;
|
2005-08-18 11:07:14 +02:00
|
|
|
bool abort_on_null;
|
2003-02-12 20:55:37 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2003-09-02 18:56:55 +02:00
|
|
|
Item_bool_func2(Item *a,Item *b)
|
2005-08-18 11:07:14 +02:00
|
|
|
:Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec();
|
2002-11-28 00:00:09 +01:00
|
|
|
void set_cmp_func()
|
2002-11-15 19:32:09 +01:00
|
|
|
{
|
2009-11-17 15:06:46 +01:00
|
|
|
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, TRUE);
|
2002-11-15 19:32:09 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_OP; }
|
|
|
|
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
|
|
|
|
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
|
2008-02-22 11:30:33 +01:00
|
|
|
|
|
|
|
virtual inline void print(String *str, enum_query_type query_type)
|
|
|
|
{
|
|
|
|
Item_func::print_op(str, query_type);
|
|
|
|
}
|
|
|
|
|
2001-10-04 01:44:18 +02:00
|
|
|
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
2004-08-31 20:10:57 +02:00
|
|
|
bool is_bool_func() { return 1; }
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return 1; }
|
2007-04-20 12:14:09 +02:00
|
|
|
void top_level_item() { abort_on_null= TRUE; }
|
2010-04-16 13:42:34 +02:00
|
|
|
void cleanup()
|
|
|
|
{
|
|
|
|
Item_int_func::cleanup();
|
|
|
|
cmp.cleanup();
|
|
|
|
}
|
2002-11-07 22:45:19 +01:00
|
|
|
|
2002-11-28 00:00:09 +01:00
|
|
|
friend class Arg_comparator;
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_bool_rowready_func2 :public Item_bool_func2
|
|
|
|
{
|
|
|
|
public:
|
A fix and test case for Bug#5987 "subselect in bool function
crashes server (prepared statements)": the bug was that all boolean
items always recovered its original arguments at statement cleanup
stage.
This collided with Item_subselect::select_transformer, which tries to
permanently change the item tree to use a transformed subselect instead of
original one.
So we had this call sequence for prepare:
mysql_stmt_prepare -> JOIN::prepare ->
Item_subselect::fix_fields -> the item tree gets transformed ->
Item_bool_rowready_func2::cleanup, item tree is recovered to original
state, while it shouldn't have been;
mysql_stmt_execute -> attempts to execute a broken tree -> crash.
Now instead of bluntly recovering all arguments of bool functions in
Item_bool_rowready_func2::cleanup, we recover only those
which were changed, and do it in one place.
There still would exist a possibility for a collision with subselect
tranformation, if permanent and temporary changes were performed at the
same stage.
But fortunately subselect transformation is always done first, so it
doesn't conflict with the optimization done by propogate_cond_constants.
Now we have:
mysql_stmt_prepare -> JOIN::prepare -> subselect transformation
permanently changes the tree -> cleanup doesn't recover anything,
because nothing was registered for recovery.
mysql_stmt_execute -> JOIN::prepare (the tree is already transformed,
so it doesn't change), JOIN::optimize ->
propogate_cond_constants -> temporary changes the item tree
with constants -> JOIN::execute -> cleanup ->
the changes done by propogate_cond_constants are recovered, as
they were registered for recovery.
2004-10-10 00:39:22 +02:00
|
|
|
Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
|
2002-11-15 19:32:09 +01:00
|
|
|
{
|
2005-01-24 13:25:44 +01:00
|
|
|
allowed_arg_cols= 0; // Fetch this value from first argument
|
2002-11-15 19:32:09 +01:00
|
|
|
}
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
|
|
|
virtual Item *negated_item();
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
bool subst_argument_checker(uchar **arg) { return TRUE; }
|
2002-11-15 19:32:09 +01:00
|
|
|
};
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
class Item_func_not :public Item_bool_func
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_not(Item *a) :Item_bool_func(a) {}
|
|
|
|
longlong val_int();
|
2003-10-31 10:02:16 +01:00
|
|
|
enum Functype functype() const { return NOT_FUNC; }
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *func_name() const { return "not"; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2004-11-18 17:10:07 +01:00
|
|
|
class Item_maxmin_subselect;
|
2004-06-11 07:27:21 +02:00
|
|
|
|
|
|
|
/*
|
2006-10-31 18:51:09 +01:00
|
|
|
trigcond<param>(arg) ::= param? arg : TRUE
|
|
|
|
|
2004-06-11 07:27:21 +02:00
|
|
|
The class Item_func_trig_cond is used for guarded predicates
|
|
|
|
which are employed only for internal purposes.
|
2006-10-31 18:51:09 +01:00
|
|
|
A guarded predicate is an object consisting of an a regular or
|
2004-06-11 07:27:21 +02:00
|
|
|
a guarded predicate P and a pointer to a boolean guard variable g.
|
|
|
|
A guarded predicate P/g is evaluated to true if the value of the
|
|
|
|
guard g is false, otherwise it is evaluated to the same value that
|
|
|
|
the predicate P: val(P/g)= g ? val(P):true.
|
|
|
|
Guarded predicates allow us to include predicates into a conjunction
|
|
|
|
conditionally. Currently they are utilized for pushed down predicates
|
|
|
|
in queries with outer join operations.
|
|
|
|
|
|
|
|
In the future, probably, it makes sense to extend this class to
|
|
|
|
the objects consisting of three elements: a predicate P, a pointer
|
|
|
|
to a variable g and a firing value s with following evaluation
|
|
|
|
rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only
|
|
|
|
one item for the objects of the form P/g1/g2...
|
|
|
|
|
|
|
|
Objects of this class are built only for query execution after
|
|
|
|
the execution plan has been already selected. That's why this
|
|
|
|
class needs only val_int out of generic methods.
|
2006-10-31 18:51:09 +01:00
|
|
|
|
|
|
|
Current uses of Item_func_trig_cond objects:
|
|
|
|
- To wrap selection conditions when executing outer joins
|
|
|
|
- To wrap condition that is pushed down into subquery
|
2004-06-11 07:27:21 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_trig_cond: public Item_bool_func
|
|
|
|
{
|
|
|
|
bool *trig_var;
|
|
|
|
public:
|
|
|
|
Item_func_trig_cond(Item *a, bool *f) : Item_bool_func(a) { trig_var= f; }
|
|
|
|
longlong val_int() { return *trig_var ? args[0]->val_int() : 1; }
|
|
|
|
enum Functype functype() const { return TRIG_COND_FUNC; };
|
|
|
|
const char *func_name() const { return "trigcond"; };
|
2005-01-18 21:50:42 +01:00
|
|
|
bool const_item() const { return FALSE; }
|
2007-01-12 21:22:41 +01:00
|
|
|
bool *get_trig_var() { return trig_var; }
|
2004-06-11 07:27:21 +02:00
|
|
|
};
|
|
|
|
|
2003-07-24 14:26:21 +02:00
|
|
|
class Item_func_not_all :public Item_func_not
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
/* allow to check presence of values in max/min optimization */
|
2004-11-18 17:10:07 +01:00
|
|
|
Item_sum_hybrid *test_sum_item;
|
|
|
|
Item_maxmin_subselect *test_sub_item;
|
|
|
|
|
2003-07-24 14:26:21 +02:00
|
|
|
bool abort_on_null;
|
|
|
|
public:
|
2003-10-16 14:54:47 +02:00
|
|
|
bool show;
|
|
|
|
|
2004-11-18 17:10:07 +01:00
|
|
|
Item_func_not_all(Item *a)
|
|
|
|
:Item_func_not(a), test_sum_item(0), test_sub_item(0), abort_on_null(0),
|
|
|
|
show(0)
|
|
|
|
{}
|
2003-07-24 14:26:21 +02:00
|
|
|
virtual void top_level_item() { abort_on_null= 1; }
|
|
|
|
bool top_level() { return abort_on_null; }
|
|
|
|
longlong val_int();
|
2003-10-31 10:02:16 +01:00
|
|
|
enum Functype functype() const { return NOT_ALL_FUNC; }
|
2003-10-16 14:54:47 +02:00
|
|
|
const char *func_name() const { return "<not>"; }
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2004-11-18 17:10:07 +01:00
|
|
|
void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; };
|
|
|
|
void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; };
|
|
|
|
bool empty_underlying_subquery();
|
2006-07-21 01:04:04 +02:00
|
|
|
Item *neg_transformer(THD *thd);
|
2003-07-24 14:26:21 +02:00
|
|
|
};
|
|
|
|
|
2004-11-18 17:10:07 +01:00
|
|
|
|
|
|
|
class Item_func_nop_all :public Item_func_not_all
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
Item_func_nop_all(Item *a) :Item_func_not_all(a) {}
|
|
|
|
longlong val_int();
|
|
|
|
const char *func_name() const { return "<nop>"; }
|
2006-07-21 01:04:04 +02:00
|
|
|
Item *neg_transformer(THD *thd);
|
2004-11-18 17:10:07 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_eq :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-09-02 18:56:55 +02:00
|
|
|
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return EQ_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return EQ_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
|
|
|
const char *func_name() const { return "="; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2002-11-28 08:11:35 +01:00
|
|
|
class Item_func_equal :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2002-11-28 19:58:23 +01:00
|
|
|
Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
2000-12-15 15:12:31 +01:00
|
|
|
void fix_length_and_dec();
|
2005-03-11 00:17:03 +01:00
|
|
|
table_map not_null_tables() const { return 0; }
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Functype functype() const { return EQUAL_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return EQUAL_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
|
|
|
const char *func_name() const { return "<=>"; }
|
2004-08-29 22:14:46 +02:00
|
|
|
Item *neg_transformer(THD *thd) { return 0; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_ge :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return GE_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return LE_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
|
|
|
const char *func_name() const { return ">="; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_gt :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return GT_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return LT_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
|
|
|
const char *func_name() const { return ">"; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_le :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return LE_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return GE_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
|
|
|
const char *func_name() const { return "<="; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_lt :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return LT_FUNC; }
|
|
|
|
enum Functype rev_functype() const { return GT_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
|
|
|
const char *func_name() const { return "<"; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-11-15 19:32:09 +01:00
|
|
|
class Item_func_ne :public Item_bool_rowready_func2
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return NE_FUNC; }
|
|
|
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
2003-06-30 18:52:30 +02:00
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *func_name() const { return "<>"; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *negated_item();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
item_cmpfunc.h:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The classes Item_func_between, Item_func_if, Item_func_in are modified.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expressions.
The class Item_func_opt_neg is added to factor out the functionality
common for the modified classes Item_func_between and Item_func_in.
item_cmpfunc.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Added Item_func_between::fix_fields(), Item_func_if::fix_fields(),
Item_func_in::fix_fields(). They correct generic calculation of
the not_null_tables attribute when it is needed.
Modified Item_func_between::val_int(), Item_func_in::val_int().
opt_range.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The function get_mm_tree() is modified. There cannot be NOT before
BETWEEN/IN anymore. Rather Item_func_between/in objects can represent
now [NOT]BETWEEN/IN expressions.
sql_yacc.yy:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expresions.
join_outer.result:
Fixed some testcases results (bugs #12101, #12102)
join_outer.test:
Added testcases for bugs #12101, #12102
2005-09-06 16:03:08 +02:00
|
|
|
/*
|
|
|
|
The class Item_func_opt_neg is defined to factor out the functionality
|
|
|
|
common for the classes Item_func_between and Item_func_in. The objects
|
|
|
|
of these classes can express predicates or there negations.
|
|
|
|
The alternative approach would be to create pairs Item_func_between,
|
|
|
|
Item_func_notbetween and Item_func_in, Item_func_notin.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_opt_neg :public Item_int_func
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool negated; /* <=> the item represents NOT <func> */
|
|
|
|
bool pred_level; /* <=> [NOT] <func> is used on a predicate level */
|
|
|
|
public:
|
|
|
|
Item_func_opt_neg(Item *a, Item *b, Item *c)
|
|
|
|
:Item_int_func(a, b, c), negated(0), pred_level(0) {}
|
|
|
|
Item_func_opt_neg(List<Item> &list)
|
|
|
|
:Item_int_func(list), negated(0), pred_level(0) {}
|
|
|
|
public:
|
|
|
|
inline void negate() { negated= !negated; }
|
|
|
|
inline void top_level_item() { pred_level= 1; }
|
|
|
|
Item *neg_transformer(THD *thd)
|
|
|
|
{
|
|
|
|
negated= !negated;
|
|
|
|
return this;
|
|
|
|
}
|
2007-04-03 23:32:16 +02:00
|
|
|
bool eq(const Item *item, bool binary_cmp) const;
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
bool subst_argument_checker(uchar **arg) { return TRUE; }
|
item_cmpfunc.h:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The classes Item_func_between, Item_func_if, Item_func_in are modified.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expressions.
The class Item_func_opt_neg is added to factor out the functionality
common for the modified classes Item_func_between and Item_func_in.
item_cmpfunc.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Added Item_func_between::fix_fields(), Item_func_if::fix_fields(),
Item_func_in::fix_fields(). They correct generic calculation of
the not_null_tables attribute when it is needed.
Modified Item_func_between::val_int(), Item_func_in::val_int().
opt_range.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The function get_mm_tree() is modified. There cannot be NOT before
BETWEEN/IN anymore. Rather Item_func_between/in objects can represent
now [NOT]BETWEEN/IN expressions.
sql_yacc.yy:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expresions.
join_outer.result:
Fixed some testcases results (bugs #12101, #12102)
join_outer.test:
Added testcases for bugs #12101, #12102
2005-09-06 16:03:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_between :public Item_func_opt_neg
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-06-27 09:02:08 +02:00
|
|
|
DTCollation cmp_collation;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
|
|
|
Item_result cmp_type;
|
|
|
|
String value0,value1,value2;
|
2007-04-26 22:40:35 +02:00
|
|
|
/* TRUE <=> arguments will be compared as dates. */
|
|
|
|
bool compare_as_dates;
|
|
|
|
/* Comparators used for DATE/DATETIME comparison. */
|
|
|
|
Arg_comparator ge_cmp, le_cmp;
|
item_cmpfunc.h:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The classes Item_func_between, Item_func_if, Item_func_in are modified.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expressions.
The class Item_func_opt_neg is added to factor out the functionality
common for the modified classes Item_func_between and Item_func_in.
item_cmpfunc.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Added Item_func_between::fix_fields(), Item_func_if::fix_fields(),
Item_func_in::fix_fields(). They correct generic calculation of
the not_null_tables attribute when it is needed.
Modified Item_func_between::val_int(), Item_func_in::val_int().
opt_range.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The function get_mm_tree() is modified. There cannot be NOT before
BETWEEN/IN anymore. Rather Item_func_between/in objects can represent
now [NOT]BETWEEN/IN expressions.
sql_yacc.yy:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expresions.
join_outer.result:
Fixed some testcases results (bugs #12101, #12102)
join_outer.test:
Added testcases for bugs #12101, #12102
2005-09-06 16:03:08 +02:00
|
|
|
Item_func_between(Item *a, Item *b, Item *c)
|
2007-04-26 22:40:35 +02:00
|
|
|
:Item_func_opt_neg(a, b, c), compare_as_dates(FALSE) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
|
|
|
|
enum Functype functype() const { return BETWEEN; }
|
|
|
|
const char *func_name() const { return "between"; }
|
2005-09-06 21:49:54 +02:00
|
|
|
bool fix_fields(THD *, Item **);
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec();
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2005-05-06 10:39:30 +02:00
|
|
|
bool is_bool_func() { return 1; }
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return 1; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_strcmp :public Item_bool_func2
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
|
|
|
|
longlong val_int();
|
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
|
|
|
const char *func_name() const { return "strcmp"; }
|
2008-02-22 11:30:33 +01:00
|
|
|
|
|
|
|
virtual inline void print(String *str, enum_query_type query_type)
|
|
|
|
{
|
|
|
|
Item_func::print(str, query_type);
|
|
|
|
}
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
void fix_length_and_dec()
|
|
|
|
{
|
|
|
|
Item_bool_func2::fix_length_and_dec();
|
|
|
|
fix_char_length(2); // returns "1" or "0" or "-1"
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
struct interval_range
|
|
|
|
{
|
|
|
|
Item_result type;
|
|
|
|
double dbl;
|
|
|
|
my_decimal dec;
|
|
|
|
};
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_func_interval :public Item_int_func
|
|
|
|
{
|
2003-01-26 20:01:45 +01:00
|
|
|
Item_row *row;
|
2005-02-08 23:50:45 +01:00
|
|
|
my_bool use_decimal_comparison;
|
|
|
|
interval_range *intervals;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2003-01-26 20:01:45 +01:00
|
|
|
Item_func_interval(Item_row *a)
|
2005-01-24 13:25:44 +01:00
|
|
|
:Item_int_func(a),row(a),intervals(0)
|
|
|
|
{
|
|
|
|
allowed_arg_cols= 0; // Fetch this value from first argument
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
void fix_length_and_dec();
|
|
|
|
const char *func_name() const { return "interval"; }
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return 2; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-06-02 16:27:02 +02:00
|
|
|
class Item_func_coalesce :public Item_func_numhybrid
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
protected:
|
2007-09-22 09:49:27 +02:00
|
|
|
enum_field_types cached_field_type;
|
2005-06-02 16:27:02 +02:00
|
|
|
Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
|
2005-02-08 23:50:45 +01:00
|
|
|
public:
|
2005-06-02 16:27:02 +02:00
|
|
|
Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
|
|
|
|
double real_op();
|
|
|
|
longlong int_op();
|
|
|
|
String *str_op(String *);
|
|
|
|
my_decimal *decimal_op(my_decimal *);
|
2005-02-08 23:50:45 +01:00
|
|
|
void fix_length_and_dec();
|
2005-06-02 16:27:02 +02:00
|
|
|
void find_num_type() {}
|
|
|
|
enum Item_result result_type () const { return hybrid_type; }
|
2005-02-08 23:50:45 +01:00
|
|
|
const char *func_name() const { return "coalesce"; }
|
|
|
|
table_map not_null_tables() const { return 0; }
|
2007-09-22 09:49:27 +02:00
|
|
|
enum_field_types field_type() const { return cached_field_type; }
|
2005-02-08 23:50:45 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_ifnull :public Item_func_coalesce
|
|
|
|
{
|
|
|
|
protected:
|
2003-08-28 01:11:54 +02:00
|
|
|
bool field_type_defined;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2005-02-08 23:50:45 +01:00
|
|
|
Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
|
2005-06-02 16:27:02 +02:00
|
|
|
double real_op();
|
|
|
|
longlong int_op();
|
|
|
|
String *str_op(String *str);
|
|
|
|
my_decimal *decimal_op(my_decimal *);
|
2003-08-28 01:11:54 +02:00
|
|
|
enum_field_types field_type() const;
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec();
|
|
|
|
const char *func_name() const { return "ifnull"; }
|
2003-08-28 01:11:54 +02:00
|
|
|
Field *tmp_table_field(TABLE *table);
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const;
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_if :public Item_func
|
|
|
|
{
|
|
|
|
enum Item_result cached_result_type;
|
2007-09-22 09:49:27 +02:00
|
|
|
enum_field_types cached_field_type;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_if(Item *a,Item *b,Item *c)
|
|
|
|
:Item_func(a,b,c), cached_result_type(INT_RESULT)
|
|
|
|
{}
|
2004-11-11 19:39:35 +01:00
|
|
|
double val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
String *val_str(String *str);
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *val_decimal(my_decimal *);
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Item_result result_type () const { return cached_result_type; }
|
2007-09-22 09:49:27 +02:00
|
|
|
enum_field_types field_type() const { return cached_field_type; }
|
2005-09-06 21:49:54 +02:00
|
|
|
bool fix_fields(THD *, Item **);
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec();
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const;
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *func_name() const { return "if"; }
|
2011-08-19 09:06:50 +02:00
|
|
|
private:
|
|
|
|
void cache_type_info(Item *source);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_nullif :public Item_bool_func2
|
|
|
|
{
|
|
|
|
enum Item_result cached_result_type;
|
|
|
|
public:
|
2003-02-12 20:55:37 +01:00
|
|
|
Item_func_nullif(Item *a,Item *b)
|
|
|
|
:Item_bool_func2(a,b), cached_result_type(INT_RESULT)
|
|
|
|
{}
|
2004-11-11 19:39:35 +01:00
|
|
|
double val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
String *val_str(String *str);
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *val_decimal(my_decimal *);
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Item_result result_type () const { return cached_result_type; }
|
|
|
|
void fix_length_and_dec();
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return args[0]->decimal_precision(); }
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *func_name() const { return "nullif"; }
|
2008-02-22 11:30:33 +01:00
|
|
|
|
|
|
|
virtual inline void print(String *str, enum_query_type query_type)
|
|
|
|
{
|
|
|
|
Item_func::print(str, query_type);
|
|
|
|
}
|
|
|
|
|
2003-06-26 04:38:19 +02:00
|
|
|
table_map not_null_tables() const { return 0; }
|
2004-09-18 11:06:44 +02:00
|
|
|
bool is_null();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Functions to handle the optimized IN */
|
|
|
|
|
2006-04-25 21:33:31 +02:00
|
|
|
|
|
|
|
/* A vector of values of some type */
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class in_vector :public Sql_alloc
|
|
|
|
{
|
2006-04-25 21:33:31 +02:00
|
|
|
public:
|
2000-07-31 21:29:14 +02:00
|
|
|
char *base;
|
|
|
|
uint size;
|
2003-06-27 10:52:38 +02:00
|
|
|
qsort2_cmp compare;
|
|
|
|
CHARSET_INFO *collation;
|
2000-07-31 21:29:14 +02:00
|
|
|
uint count;
|
|
|
|
uint used_count;
|
2002-12-08 02:19:03 +01:00
|
|
|
in_vector() {}
|
2003-06-27 10:52:38 +02:00
|
|
|
in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
|
|
|
|
CHARSET_INFO *cmp_coll)
|
2000-07-31 21:29:14 +02:00
|
|
|
:base((char*) sql_calloc(elements*element_length)),
|
2003-06-27 10:52:38 +02:00
|
|
|
size(element_length), compare(cmp_func), collation(cmp_coll),
|
|
|
|
count(elements), used_count(elements) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
virtual ~in_vector() {}
|
|
|
|
virtual void set(uint pos,Item *item)=0;
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
virtual uchar *get_value(Item *item)=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
void sort()
|
2002-11-07 02:54:00 +01:00
|
|
|
{
|
2007-10-17 18:08:58 +02:00
|
|
|
my_qsort2(base,used_count,size,compare,collation);
|
2002-11-07 02:54:00 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
int find(Item *item);
|
2006-04-25 21:33:31 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Create an instance of Item_{type} (e.g. Item_decimal) constant object
|
|
|
|
which type allows it to hold an element of this vector without any
|
|
|
|
conversions.
|
|
|
|
The purpose of this function is to be able to get elements of this
|
|
|
|
vector in form of Item_xxx constants without creating Item_xxx object
|
|
|
|
for every array element you get (i.e. this implements "FlyWeight" pattern)
|
|
|
|
*/
|
|
|
|
virtual Item* create_item() { return NULL; }
|
|
|
|
|
|
|
|
/*
|
|
|
|
Store the value at position #pos into provided item object
|
|
|
|
SYNOPSIS
|
|
|
|
value_to_item()
|
|
|
|
pos Index of value to store
|
|
|
|
item Constant item to store value into. The item must be of the same
|
|
|
|
type that create_item() returns.
|
|
|
|
*/
|
|
|
|
virtual void value_to_item(uint pos, Item *item) { }
|
|
|
|
|
|
|
|
/* Compare values number pos1 and pos2 for equality */
|
|
|
|
bool compare_elems(uint pos1, uint pos2)
|
|
|
|
{
|
|
|
|
return test(compare(collation, base + pos1*size, base + pos2*size));
|
|
|
|
}
|
2006-09-26 18:52:54 +02:00
|
|
|
virtual Item_result result_type()= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class in_string :public in_vector
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
char buff[STRING_BUFFER_USUAL_SIZE];
|
2000-07-31 21:29:14 +02:00
|
|
|
String tmp;
|
|
|
|
public:
|
2003-06-27 10:52:38 +02:00
|
|
|
in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
|
2000-07-31 21:29:14 +02:00
|
|
|
~in_string();
|
|
|
|
void set(uint pos,Item *item);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *get_value(Item *item);
|
2006-04-25 21:33:31 +02:00
|
|
|
Item* create_item()
|
|
|
|
{
|
|
|
|
return new Item_string(collation);
|
|
|
|
}
|
|
|
|
void value_to_item(uint pos, Item *item)
|
|
|
|
{
|
|
|
|
String *str=((String*) base)+pos;
|
|
|
|
Item_string *to= (Item_string*)item;
|
|
|
|
to->str_value= *str;
|
|
|
|
}
|
2006-09-26 18:52:54 +02:00
|
|
|
Item_result result_type() { return STRING_RESULT; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class in_longlong :public in_vector
|
|
|
|
{
|
2007-05-07 20:20:43 +02:00
|
|
|
protected:
|
2007-03-02 15:25:56 +01:00
|
|
|
/*
|
|
|
|
Here we declare a temporary variable (tmp) of the same type as the
|
|
|
|
elements of this vector. tmp is used in finding if a given value is in
|
|
|
|
the list.
|
|
|
|
*/
|
|
|
|
struct packed_longlong
|
|
|
|
{
|
|
|
|
longlong val;
|
|
|
|
longlong unsigned_flag; // Use longlong, not bool, to preserve alignment
|
|
|
|
} tmp;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
|
|
|
in_longlong(uint elements);
|
|
|
|
void set(uint pos,Item *item);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *get_value(Item *item);
|
2006-04-25 21:33:31 +02:00
|
|
|
|
|
|
|
Item* create_item()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
We're created a signed INT, this may not be correct in
|
|
|
|
general case (see BUG#19342).
|
|
|
|
*/
|
2006-04-25 23:21:33 +02:00
|
|
|
return new Item_int((longlong)0);
|
2006-04-25 21:33:31 +02:00
|
|
|
}
|
|
|
|
void value_to_item(uint pos, Item *item)
|
|
|
|
{
|
2007-03-02 15:25:56 +01:00
|
|
|
((Item_int*) item)->value= ((packed_longlong*) base)[pos].val;
|
2007-03-02 18:32:46 +01:00
|
|
|
((Item_int*) item)->unsigned_flag= (my_bool)
|
2007-03-02 15:25:56 +01:00
|
|
|
((packed_longlong*) base)[pos].unsigned_flag;
|
2006-04-25 21:33:31 +02:00
|
|
|
}
|
2006-09-26 18:52:54 +02:00
|
|
|
Item_result result_type() { return INT_RESULT; }
|
2007-03-02 15:25:56 +01:00
|
|
|
|
|
|
|
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2007-05-07 20:20:43 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Class to represent a vector of constant DATE/DATETIME values.
|
|
|
|
Values are obtained with help of the get_datetime_value() function.
|
|
|
|
If the left item is a constant one then its value is cached in the
|
|
|
|
lval_cache variable.
|
|
|
|
*/
|
|
|
|
class in_datetime :public in_longlong
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
THD *thd;
|
|
|
|
/* An item used to issue warnings. */
|
|
|
|
Item *warn_item;
|
|
|
|
/* Cache for the left item. */
|
|
|
|
Item *lval_cache;
|
|
|
|
|
|
|
|
in_datetime(Item *warn_item_arg, uint elements)
|
|
|
|
:in_longlong(elements), thd(current_thd), warn_item(warn_item_arg),
|
|
|
|
lval_cache(0) {};
|
|
|
|
void set(uint pos,Item *item);
|
2007-05-24 18:47:58 +02:00
|
|
|
uchar *get_value(Item *item);
|
2007-05-07 20:20:43 +02:00
|
|
|
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
|
|
|
|
};
|
|
|
|
|
2007-07-30 10:33:50 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class in_double :public in_vector
|
|
|
|
{
|
|
|
|
double tmp;
|
|
|
|
public:
|
|
|
|
in_double(uint elements);
|
|
|
|
void set(uint pos,Item *item);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *get_value(Item *item);
|
2006-04-25 21:33:31 +02:00
|
|
|
Item *create_item()
|
|
|
|
{
|
2007-07-30 10:33:50 +02:00
|
|
|
return new Item_float(0.0, 0);
|
2006-04-25 21:33:31 +02:00
|
|
|
}
|
|
|
|
void value_to_item(uint pos, Item *item)
|
|
|
|
{
|
|
|
|
((Item_float*)item)->value= ((double*) base)[pos];
|
|
|
|
}
|
2006-09-26 18:52:54 +02:00
|
|
|
Item_result result_type() { return REAL_RESULT; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2007-07-30 10:33:50 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
class in_decimal :public in_vector
|
|
|
|
{
|
|
|
|
my_decimal val;
|
|
|
|
public:
|
|
|
|
in_decimal(uint elements);
|
|
|
|
void set(uint pos, Item *item);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *get_value(Item *item);
|
2006-04-25 21:33:31 +02:00
|
|
|
Item *create_item()
|
|
|
|
{
|
|
|
|
return new Item_decimal(0, FALSE);
|
|
|
|
}
|
|
|
|
void value_to_item(uint pos, Item *item)
|
|
|
|
{
|
|
|
|
my_decimal *dec= ((my_decimal *)base) + pos;
|
|
|
|
Item_decimal *item_dec= (Item_decimal*)item;
|
|
|
|
item_dec->set_decimal_value(dec);
|
|
|
|
}
|
2006-09-26 18:52:54 +02:00
|
|
|
Item_result result_type() { return DECIMAL_RESULT; }
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/*
|
|
|
|
** Classes for easy comparing of non const items
|
|
|
|
*/
|
|
|
|
|
|
|
|
class cmp_item :public Sql_alloc
|
|
|
|
{
|
|
|
|
public:
|
2003-03-04 15:01:59 +01:00
|
|
|
CHARSET_INFO *cmp_charset;
|
|
|
|
cmp_item() { cmp_charset= &my_charset_bin; }
|
2000-07-31 21:29:14 +02:00
|
|
|
virtual ~cmp_item() {}
|
2002-12-08 02:19:03 +01:00
|
|
|
virtual void store_value(Item *item)= 0;
|
|
|
|
virtual int cmp(Item *item)= 0;
|
|
|
|
// for optimized IN with row
|
|
|
|
virtual int compare(cmp_item *item)= 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
static cmp_item* get_comparator(Item_result type, CHARSET_INFO *cs);
|
2002-12-08 02:19:03 +01:00
|
|
|
virtual cmp_item *make_same()= 0;
|
|
|
|
virtual void store_value_by_template(cmp_item *tmpl, Item *item)
|
|
|
|
{
|
|
|
|
store_value(item);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2002-12-08 02:19:03 +01:00
|
|
|
class cmp_item_string :public cmp_item
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
String *value_res;
|
|
|
|
public:
|
2006-09-26 18:52:54 +02:00
|
|
|
cmp_item_string () {}
|
2003-03-04 15:01:59 +01:00
|
|
|
cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
|
2006-09-26 18:52:54 +02:00
|
|
|
void set_charset(CHARSET_INFO *cs) { cmp_charset= cs; }
|
2002-12-08 02:19:03 +01:00
|
|
|
friend class cmp_item_sort_string;
|
|
|
|
friend class cmp_item_sort_string_in_static;
|
|
|
|
};
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2002-12-08 02:19:03 +01:00
|
|
|
class cmp_item_sort_string :public cmp_item_string
|
|
|
|
{
|
|
|
|
protected:
|
2005-02-08 23:50:45 +01:00
|
|
|
char value_buff[STRING_BUFFER_USUAL_SIZE];
|
2002-12-08 02:19:03 +01:00
|
|
|
String value;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2006-09-26 18:52:54 +02:00
|
|
|
cmp_item_sort_string():
|
|
|
|
cmp_item_string() {}
|
2003-03-04 15:01:59 +01:00
|
|
|
cmp_item_sort_string(CHARSET_INFO *cs):
|
|
|
|
cmp_item_string(cs),
|
|
|
|
value(value_buff, sizeof(value_buff), cs) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
void store_value(Item *item)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
|
|
|
value_res= item->val_str(&value);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
int cmp(Item *arg)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
char buff[STRING_BUFFER_USUAL_SIZE];
|
2003-03-07 09:21:32 +01:00
|
|
|
String tmp(buff, sizeof(buff), cmp_charset), *res;
|
2005-12-09 21:01:52 +01:00
|
|
|
res= arg->val_str(&tmp);
|
|
|
|
return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) :
|
|
|
|
(res ? -1 : 0));
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
2006-12-14 23:51:37 +01:00
|
|
|
int compare(cmp_item *ci)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
cmp_item_string *l_cmp= (cmp_item_string *) ci;
|
|
|
|
return sortcmp(value_res, l_cmp->value_res, cmp_charset);
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
|
|
|
cmp_item *make_same();
|
2006-09-26 18:52:54 +02:00
|
|
|
void set_charset(CHARSET_INFO *cs)
|
|
|
|
{
|
|
|
|
cmp_charset= cs;
|
|
|
|
value.set_quick(value_buff, sizeof(value_buff), cs);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class cmp_item_int :public cmp_item
|
|
|
|
{
|
|
|
|
longlong value;
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
cmp_item_int() {} /* Remove gcc warning */
|
2000-07-31 21:29:14 +02:00
|
|
|
void store_value(Item *item)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
|
|
|
value= item->val_int();
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
int cmp(Item *arg)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
|
|
|
return value != arg->val_int();
|
|
|
|
}
|
2006-12-14 23:51:37 +01:00
|
|
|
int compare(cmp_item *ci)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
cmp_item_int *l_cmp= (cmp_item_int *)ci;
|
|
|
|
return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1);
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
|
|
|
cmp_item *make_same();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2007-05-07 20:20:43 +02:00
|
|
|
/*
|
|
|
|
Compare items in the DATETIME context.
|
|
|
|
Values are obtained with help of the get_datetime_value() function.
|
|
|
|
If the left item is a constant one then its value is cached in the
|
|
|
|
lval_cache variable.
|
|
|
|
*/
|
|
|
|
class cmp_item_datetime :public cmp_item
|
|
|
|
{
|
2008-11-26 09:28:17 +01:00
|
|
|
longlong value;
|
2007-05-07 20:20:43 +02:00
|
|
|
public:
|
|
|
|
THD *thd;
|
|
|
|
/* Item used for issuing warnings. */
|
|
|
|
Item *warn_item;
|
|
|
|
/* Cache for the left item. */
|
|
|
|
Item *lval_cache;
|
|
|
|
|
|
|
|
cmp_item_datetime(Item *warn_item_arg)
|
|
|
|
:thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}
|
|
|
|
void store_value(Item *item);
|
|
|
|
int cmp(Item *arg);
|
|
|
|
int compare(cmp_item *ci);
|
|
|
|
cmp_item *make_same();
|
|
|
|
};
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class cmp_item_real :public cmp_item
|
|
|
|
{
|
|
|
|
double value;
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
cmp_item_real() {} /* Remove gcc warning */
|
2000-07-31 21:29:14 +02:00
|
|
|
void store_value(Item *item)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
value= item->val_real();
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
int cmp(Item *arg)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
return value != arg->val_real();
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
2006-12-14 23:51:37 +01:00
|
|
|
int compare(cmp_item *ci)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
cmp_item_real *l_cmp= (cmp_item_real *) ci;
|
|
|
|
return (value < l_cmp->value)? -1 : ((value == l_cmp->value) ? 0 : 1);
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
|
|
|
cmp_item *make_same();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
class cmp_item_decimal :public cmp_item
|
|
|
|
{
|
|
|
|
my_decimal value;
|
|
|
|
public:
|
2006-02-25 16:46:30 +01:00
|
|
|
cmp_item_decimal() {} /* Remove gcc warning */
|
2005-02-08 23:50:45 +01:00
|
|
|
void store_value(Item *item);
|
|
|
|
int cmp(Item *arg);
|
|
|
|
int compare(cmp_item *c);
|
|
|
|
cmp_item *make_same();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-12-08 02:19:03 +01:00
|
|
|
/*
|
|
|
|
cmp_item for optimized IN with row (right part string, which never
|
|
|
|
be changed)
|
|
|
|
*/
|
|
|
|
|
|
|
|
class cmp_item_sort_string_in_static :public cmp_item_string
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
String value;
|
|
|
|
public:
|
2003-03-04 15:01:59 +01:00
|
|
|
cmp_item_sort_string_in_static(CHARSET_INFO *cs):
|
|
|
|
cmp_item_string(cs) {}
|
2002-12-08 02:19:03 +01:00
|
|
|
void store_value(Item *item)
|
|
|
|
{
|
|
|
|
value_res= item->val_str(&value);
|
|
|
|
}
|
|
|
|
int cmp(Item *item)
|
|
|
|
{
|
|
|
|
// Should never be called
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 1;
|
|
|
|
}
|
2006-12-14 23:51:37 +01:00
|
|
|
int compare(cmp_item *ci)
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
cmp_item_string *l_cmp= (cmp_item_string *) ci;
|
|
|
|
return sortcmp(value_res, l_cmp->value_res, cmp_charset);
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
2003-11-19 16:31:57 +01:00
|
|
|
cmp_item *make_same()
|
2002-12-08 02:19:03 +01:00
|
|
|
{
|
2003-03-04 15:01:59 +01:00
|
|
|
return new cmp_item_sort_string_in_static(cmp_charset);
|
2002-12-08 02:19:03 +01:00
|
|
|
}
|
2002-12-07 18:58:05 +01:00
|
|
|
};
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2006-09-26 18:52:54 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
The class Item_func_case is the CASE ... WHEN ... THEN ... END function
|
|
|
|
implementation.
|
|
|
|
|
|
|
|
When there is no expression between CASE and the first WHEN
|
|
|
|
(the CASE expression) then this function simple checks all WHEN expressions
|
|
|
|
one after another. When some WHEN expression evaluated to TRUE then the
|
|
|
|
value of the corresponding THEN expression is returned.
|
|
|
|
|
|
|
|
When the CASE expression is specified then it is compared to each WHEN
|
|
|
|
expression individually. When an equal WHEN expression is found
|
|
|
|
corresponding THEN expression is returned.
|
|
|
|
In order to do correct comparisons several comparators are used. One for
|
|
|
|
each result type. Different result types that are used in particular
|
|
|
|
CASE ... END expression are collected in the fix_length_and_dec() member
|
|
|
|
function and only comparators for there result types are used.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Item_func_case :public Item_func
|
|
|
|
{
|
|
|
|
int first_expr_num, else_expr_num;
|
|
|
|
enum Item_result cached_result_type, left_result_type;
|
|
|
|
String tmp_value;
|
|
|
|
uint ncases;
|
|
|
|
Item_result cmp_type;
|
|
|
|
DTCollation cmp_collation;
|
2007-09-26 18:06:54 +02:00
|
|
|
enum_field_types cached_field_type;
|
2006-09-26 18:52:54 +02:00
|
|
|
cmp_item *cmp_items[5]; /* For all result types */
|
|
|
|
cmp_item *case_item;
|
|
|
|
public:
|
|
|
|
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
|
|
|
|
:Item_func(), first_expr_num(-1), else_expr_num(-1),
|
|
|
|
cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0)
|
|
|
|
{
|
|
|
|
ncases= list.elements;
|
|
|
|
if (first_expr_arg)
|
|
|
|
{
|
|
|
|
first_expr_num= list.elements;
|
|
|
|
list.push_back(first_expr_arg);
|
|
|
|
}
|
|
|
|
if (else_expr_arg)
|
|
|
|
{
|
|
|
|
else_expr_num= list.elements;
|
|
|
|
list.push_back(else_expr_arg);
|
|
|
|
}
|
|
|
|
set_arguments(list);
|
|
|
|
bzero(&cmp_items, sizeof(cmp_items));
|
|
|
|
}
|
|
|
|
double val_real();
|
|
|
|
longlong val_int();
|
|
|
|
String *val_str(String *);
|
|
|
|
my_decimal *val_decimal(my_decimal *);
|
|
|
|
bool fix_fields(THD *thd, Item **ref);
|
|
|
|
void fix_length_and_dec();
|
|
|
|
uint decimal_precision() const;
|
|
|
|
table_map not_null_tables() const { return 0; }
|
|
|
|
enum Item_result result_type () const { return cached_result_type; }
|
2007-09-26 18:06:54 +02:00
|
|
|
enum_field_types field_type() const { return cached_field_type; }
|
2006-09-26 18:52:54 +02:00
|
|
|
const char *func_name() const { return "case"; }
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2006-09-26 18:52:54 +02:00
|
|
|
Item *find_item(String *str);
|
|
|
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
2007-03-27 13:15:38 +02:00
|
|
|
void cleanup();
|
2007-10-29 10:16:26 +01:00
|
|
|
void agg_str_lengths(Item *arg);
|
|
|
|
void agg_num_lengths(Item *arg);
|
2006-09-26 18:52:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
The Item_func_in class implements the in_expr IN(values_list) function.
|
|
|
|
|
|
|
|
The current implementation distinguishes 2 cases:
|
|
|
|
1) all items in the value_list are constants and have the same
|
|
|
|
result type. This case is handled by in_vector class.
|
|
|
|
2) items in the value_list have different result types or there is some
|
|
|
|
non-constant items.
|
|
|
|
In this case Item_func_in employs several cmp_item objects to performs
|
|
|
|
comparisons of in_expr and an item from the values_list. One cmp_item
|
|
|
|
object for each result type. Different result types are collected in the
|
|
|
|
fix_length_and_dec() member function by means of collect_cmp_types()
|
|
|
|
function.
|
|
|
|
*/
|
item_cmpfunc.h:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The classes Item_func_between, Item_func_if, Item_func_in are modified.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expressions.
The class Item_func_opt_neg is added to factor out the functionality
common for the modified classes Item_func_between and Item_func_in.
item_cmpfunc.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Added Item_func_between::fix_fields(), Item_func_if::fix_fields(),
Item_func_in::fix_fields(). They correct generic calculation of
the not_null_tables attribute when it is needed.
Modified Item_func_between::val_int(), Item_func_in::val_int().
opt_range.cc:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
The function get_mm_tree() is modified. There cannot be NOT before
BETWEEN/IN anymore. Rather Item_func_between/in objects can represent
now [NOT]BETWEEN/IN expressions.
sql_yacc.yy:
Fixed bugs #12101, #12102: wrong calculation of not_null_tables()
for some expressions.
Item_func_between/in objects can represent now [NOT]BETWEEN/IN expresions.
join_outer.result:
Fixed some testcases results (bugs #12101, #12102)
join_outer.test:
Added testcases for bugs #12101, #12102
2005-09-06 16:03:08 +02:00
|
|
|
class Item_func_in :public Item_func_opt_neg
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2006-04-25 21:33:31 +02:00
|
|
|
public:
|
2007-01-15 18:15:52 +01:00
|
|
|
/*
|
|
|
|
an array of values when the right hand arguments of IN
|
|
|
|
are all SQL constant and there are no nulls
|
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
in_vector *array;
|
2002-12-06 20:55:53 +01:00
|
|
|
bool have_null;
|
2007-02-16 12:56:06 +01:00
|
|
|
/*
|
|
|
|
true when all arguments of the IN clause are of compatible types
|
|
|
|
and can be used safely as comparisons for key conditions
|
|
|
|
*/
|
|
|
|
bool arg_types_compatible;
|
2006-09-26 18:52:54 +02:00
|
|
|
Item_result left_result_type;
|
2007-05-08 20:28:24 +02:00
|
|
|
cmp_item *cmp_items[6]; /* One cmp_item for each result type */
|
2003-06-27 10:52:38 +02:00
|
|
|
DTCollation cmp_collation;
|
2006-04-25 21:33:31 +02:00
|
|
|
|
2003-07-16 08:29:16 +02:00
|
|
|
Item_func_in(List<Item> &list)
|
2007-02-16 12:56:06 +01:00
|
|
|
:Item_func_opt_neg(list), array(0), have_null(0),
|
|
|
|
arg_types_compatible(FALSE)
|
2002-12-07 18:58:05 +01:00
|
|
|
{
|
2006-09-26 18:52:54 +02:00
|
|
|
bzero(&cmp_items, sizeof(cmp_items));
|
2005-01-24 13:25:44 +01:00
|
|
|
allowed_arg_cols= 0; // Fetch this value from first argument
|
2002-12-07 18:58:05 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
2005-09-06 21:49:54 +02:00
|
|
|
bool fix_fields(THD *, Item **);
|
2000-07-31 21:29:14 +02:00
|
|
|
void fix_length_and_dec();
|
2005-05-05 17:06:49 +02:00
|
|
|
uint decimal_precision() const { return 1; }
|
2003-11-18 12:47:27 +01:00
|
|
|
void cleanup()
|
|
|
|
{
|
2006-09-26 18:52:54 +02:00
|
|
|
uint i;
|
2004-02-08 19:14:13 +01:00
|
|
|
DBUG_ENTER("Item_func_in::cleanup");
|
2004-03-17 13:26:26 +01:00
|
|
|
Item_int_func::cleanup();
|
2003-11-18 12:47:27 +01:00
|
|
|
delete array;
|
|
|
|
array= 0;
|
2007-05-08 20:28:24 +02:00
|
|
|
for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++)
|
2006-09-26 18:52:54 +02:00
|
|
|
{
|
|
|
|
delete cmp_items[i];
|
|
|
|
cmp_items[i]= 0;
|
|
|
|
}
|
2004-02-08 19:14:13 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2003-11-18 12:47:27 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
optimize_type select_optimize() const
|
2007-01-15 18:15:52 +01:00
|
|
|
{ return OPTIMIZE_KEY; }
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Functype functype() const { return IN_FUNC; }
|
|
|
|
const char *func_name() const { return " IN "; }
|
2002-12-10 17:10:00 +01:00
|
|
|
bool nulls_in_row();
|
2004-08-31 20:10:57 +02:00
|
|
|
bool is_bool_func() { return 1; }
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2007-05-08 13:54:49 +02:00
|
|
|
class cmp_item_row :public cmp_item
|
|
|
|
{
|
|
|
|
cmp_item **comparators;
|
|
|
|
uint n;
|
|
|
|
public:
|
|
|
|
cmp_item_row(): comparators(0), n(0) {}
|
|
|
|
~cmp_item_row();
|
|
|
|
void store_value(Item *item);
|
2007-05-24 18:47:58 +02:00
|
|
|
inline void alloc_comparators();
|
2007-05-08 13:54:49 +02:00
|
|
|
int cmp(Item *arg);
|
|
|
|
int compare(cmp_item *arg);
|
|
|
|
cmp_item *make_same();
|
|
|
|
void store_value_by_template(cmp_item *tmpl, Item *);
|
2007-05-24 18:47:58 +02:00
|
|
|
friend void Item_func_in::fix_length_and_dec();
|
2007-05-08 13:54:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class in_row :public in_vector
|
|
|
|
{
|
|
|
|
cmp_item_row tmp;
|
|
|
|
public:
|
|
|
|
in_row(uint elements, Item *);
|
|
|
|
~in_row();
|
|
|
|
void set(uint pos,Item *item);
|
2007-05-24 12:24:36 +02:00
|
|
|
uchar *get_value(Item *item);
|
2007-05-24 18:47:58 +02:00
|
|
|
friend void Item_func_in::fix_length_and_dec();
|
2007-05-24 12:24:36 +02:00
|
|
|
Item_result result_type() { return ROW_RESULT; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Functions used by where clause */
|
|
|
|
|
|
|
|
class Item_func_isnull :public Item_bool_func
|
|
|
|
{
|
2003-04-22 23:01:19 +02:00
|
|
|
protected:
|
2002-05-07 18:08:56 +02:00
|
|
|
longlong cached_value;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
|
|
|
Item_func_isnull(Item *a) :Item_bool_func(a) {}
|
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return ISNULL_FUNC; }
|
|
|
|
void fix_length_and_dec()
|
|
|
|
{
|
|
|
|
decimals=0; max_length=1; maybe_null=0;
|
2003-04-22 23:01:19 +02:00
|
|
|
update_used_tables();
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
const char *func_name() const { return "isnull"; }
|
|
|
|
/* Optimize case of not_null_column IS NULL */
|
2003-04-22 23:01:19 +02:00
|
|
|
virtual void update_used_tables()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
if (!args[0]->maybe_null)
|
|
|
|
{
|
2003-02-17 00:05:04 +01:00
|
|
|
used_tables_cache= 0; /* is always false */
|
2003-12-01 22:59:09 +01:00
|
|
|
const_item_cache= 1;
|
2003-02-17 00:05:04 +01:00
|
|
|
cached_value= (longlong) 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-02-17 00:05:04 +01:00
|
|
|
else
|
2002-05-07 18:08:56 +02:00
|
|
|
{
|
2003-02-17 00:05:04 +01:00
|
|
|
args[0]->update_used_tables();
|
2010-06-08 08:22:40 +02:00
|
|
|
if ((const_item_cache= !(used_tables_cache= args[0]->used_tables()) &&
|
|
|
|
!with_subselect))
|
2003-02-17 00:05:04 +01:00
|
|
|
{
|
|
|
|
/* Remember if the value is always NULL or never NULL */
|
2003-02-17 01:14:37 +01:00
|
|
|
cached_value= (longlong) args[0]->is_null();
|
2003-02-17 00:05:04 +01:00
|
|
|
}
|
2002-05-07 18:08:56 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-06-26 04:38:19 +02:00
|
|
|
table_map not_null_tables() const { return 0; }
|
2000-07-31 21:29:14 +02:00
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2003-04-22 23:01:19 +02:00
|
|
|
/* Functions used by HAVING for rewriting IN subquery */
|
|
|
|
|
|
|
|
class Item_in_subselect;
|
2006-10-31 18:51:09 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
This is like IS NOT NULL but it also remembers if it ever has
|
|
|
|
encountered a NULL.
|
|
|
|
*/
|
2003-04-22 23:01:19 +02:00
|
|
|
class Item_is_not_null_test :public Item_func_isnull
|
|
|
|
{
|
|
|
|
Item_in_subselect* owner;
|
|
|
|
public:
|
|
|
|
Item_is_not_null_test(Item_in_subselect* ow, Item *a)
|
|
|
|
:Item_func_isnull(a), owner(ow)
|
|
|
|
{}
|
2003-07-17 18:39:31 +02:00
|
|
|
enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
|
2003-04-22 23:01:19 +02:00
|
|
|
longlong val_int();
|
2003-10-12 16:56:05 +02:00
|
|
|
const char *func_name() const { return "<is_not_null_test>"; }
|
2003-04-22 23:01:19 +02:00
|
|
|
void update_used_tables();
|
2005-08-13 06:45:14 +02:00
|
|
|
/*
|
|
|
|
we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
|
|
|
|
*/
|
|
|
|
table_map used_tables() const
|
|
|
|
{ return used_tables_cache | RAND_TABLE_BIT; }
|
2003-04-22 23:01:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_func_isnotnull :public Item_bool_func
|
|
|
|
{
|
2005-03-13 23:56:25 +01:00
|
|
|
bool abort_on_null;
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2005-03-13 23:56:25 +01:00
|
|
|
Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return ISNOTNULL_FUNC; }
|
2001-10-02 04:53:00 +02:00
|
|
|
void fix_length_and_dec()
|
|
|
|
{
|
|
|
|
decimals=0; max_length=1; maybe_null=0;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *func_name() const { return "isnotnull"; }
|
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
2005-03-14 11:04:42 +01:00
|
|
|
table_map not_null_tables() const
|
|
|
|
{ return abort_on_null ? not_null_tables_cache : 0; }
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
2005-03-13 23:56:25 +01:00
|
|
|
void top_level_item() { abort_on_null=1; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
2003-06-26 04:38:19 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_func_like :public Item_bool_func2
|
|
|
|
{
|
2002-05-17 15:45:00 +02:00
|
|
|
// Turbo Boyer-Moore data
|
|
|
|
bool canDoTurboBM; // pattern is '%abcd%' case
|
|
|
|
const char* pattern;
|
|
|
|
int pattern_len;
|
|
|
|
|
|
|
|
// TurboBM buffers, *this is owner
|
|
|
|
int* bmGs; // good suffix shift table, size is pattern_len + 1
|
|
|
|
int* bmBc; // bad character shift table, size is alphabet_size
|
|
|
|
|
|
|
|
void turboBM_compute_suffixes(int* suff);
|
|
|
|
void turboBM_compute_good_suffix_shifts(int* suff);
|
|
|
|
void turboBM_compute_bad_character_shifts();
|
|
|
|
bool turboBM_matches(const char* text, int text_len) const;
|
|
|
|
enum { alphabet_size = 256 };
|
|
|
|
|
2004-06-22 17:27:16 +02:00
|
|
|
Item *escape_item;
|
2005-10-21 03:01:52 +02:00
|
|
|
|
|
|
|
bool escape_used_in_parsing;
|
2004-06-22 17:27:16 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2005-09-06 11:48:18 +02:00
|
|
|
int escape;
|
2003-12-30 16:23:38 +01:00
|
|
|
|
2005-10-21 03:01:52 +02:00
|
|
|
Item_func_like(Item *a,Item *b, Item *escape_arg, bool escape_used)
|
2004-10-14 17:03:46 +02:00
|
|
|
:Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
|
2005-10-21 03:01:52 +02:00
|
|
|
bmGs(0), bmBc(0), escape_item(escape_arg),
|
|
|
|
escape_used_in_parsing(escape_used) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
|
|
|
enum Functype functype() const { return LIKE_FUNC; }
|
|
|
|
optimize_type select_optimize() const;
|
|
|
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
|
|
|
const char *func_name() const { return "like"; }
|
2005-07-01 06:05:42 +02:00
|
|
|
bool fix_fields(THD *thd, Item **ref);
|
2006-01-14 02:55:07 +01:00
|
|
|
void cleanup();
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Item_func_regex :public Item_bool_func
|
|
|
|
{
|
2005-09-29 02:08:24 +02:00
|
|
|
my_regex_t preg;
|
2000-07-31 21:29:14 +02:00
|
|
|
bool regex_compiled;
|
|
|
|
bool regex_is_const;
|
|
|
|
String prev_regexp;
|
2003-06-26 12:45:04 +02:00
|
|
|
DTCollation cmp_collation;
|
2007-10-05 09:15:11 +02:00
|
|
|
CHARSET_INFO *regex_lib_charset;
|
|
|
|
int regex_lib_flags;
|
|
|
|
String conv;
|
2008-09-05 10:30:01 +02:00
|
|
|
int regcomp(bool send_error);
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
|
|
|
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
|
|
|
|
regex_compiled(0),regex_is_const(0) {}
|
2004-06-19 12:26:39 +02:00
|
|
|
void cleanup();
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong val_int();
|
2005-07-01 06:05:42 +02:00
|
|
|
bool fix_fields(THD *thd, Item **ref);
|
2003-10-30 11:57:26 +01:00
|
|
|
const char *func_name() const { return "regexp"; }
|
2008-02-22 11:30:33 +01:00
|
|
|
|
|
|
|
virtual inline void print(String *str, enum_query_type query_type)
|
|
|
|
{
|
|
|
|
print_op(str, query_type);
|
|
|
|
}
|
|
|
|
|
2004-02-02 14:50:14 +01:00
|
|
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef class Item COND;
|
|
|
|
|
|
|
|
class Item_cond :public Item_bool_func
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
List<Item> list;
|
2002-11-11 14:57:35 +01:00
|
|
|
bool abort_on_null;
|
2003-06-26 04:38:19 +02:00
|
|
|
table_map and_tables_cache;
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
public:
|
2002-11-11 14:57:35 +01:00
|
|
|
/* Item_cond() is only used to create top level items */
|
2003-10-31 10:02:16 +01:00
|
|
|
Item_cond(): Item_bool_func(), abort_on_null(1)
|
|
|
|
{ const_item_cache=0; }
|
2005-03-13 23:56:25 +01:00
|
|
|
Item_cond(Item *i1,Item *i2)
|
2003-09-02 18:56:55 +02:00
|
|
|
:Item_bool_func(), abort_on_null(0)
|
|
|
|
{
|
|
|
|
list.push_back(i1);
|
|
|
|
list.push_back(i2);
|
|
|
|
}
|
2004-01-19 16:53:25 +01:00
|
|
|
Item_cond(THD *thd, Item_cond *item);
|
2003-10-31 10:02:16 +01:00
|
|
|
Item_cond(List<Item> &nlist)
|
|
|
|
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
2010-02-26 12:39:25 +01:00
|
|
|
bool add(Item *item)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(item);
|
|
|
|
return list.push_back(item);
|
|
|
|
}
|
|
|
|
bool add_at_head(Item *item)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(item);
|
|
|
|
return list.push_front(item);
|
|
|
|
}
|
|
|
|
void add_at_head(List<Item> *nlist)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(nlist->elements);
|
|
|
|
list.prepand(nlist);
|
|
|
|
}
|
2005-07-01 06:05:42 +02:00
|
|
|
bool fix_fields(THD *, Item **ref);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
enum Type type() const { return COND_ITEM; }
|
|
|
|
List<Item>* argument_list() { return &list; }
|
|
|
|
table_map used_tables() const;
|
|
|
|
void update_used_tables();
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2004-10-08 17:13:09 +02:00
|
|
|
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
2004-09-14 18:28:29 +02:00
|
|
|
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
2005-07-01 06:05:42 +02:00
|
|
|
COND **conds);
|
2002-11-11 14:57:35 +01:00
|
|
|
void top_level_item() { abort_on_null=1; }
|
2003-09-02 18:56:55 +02:00
|
|
|
void copy_andor_arguments(THD *thd, Item_cond *item);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
|
|
|
|
Item *transform(Item_transformer transformer, uchar *arg);
|
2005-03-02 10:38:25 +01:00
|
|
|
void traverse_cond(Cond_traverser, void *arg, traverse_order order);
|
2004-03-17 13:26:26 +01:00
|
|
|
void neg_arguments(THD *thd);
|
2007-09-22 09:49:27 +02:00
|
|
|
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
bool subst_argument_checker(uchar **arg) { return TRUE; }
|
|
|
|
Item *compile(Item_analyzer analyzer, uchar **arg_p,
|
|
|
|
Item_transformer transformer, uchar *arg_t);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-02-19 07:21:37 +01:00
|
|
|
/*
|
2005-02-08 23:50:45 +01:00
|
|
|
The class Item_equal is used to represent conjunctions of equality
|
2004-02-19 07:21:37 +01:00
|
|
|
predicates of the form field1 = field2, and field=const in where
|
|
|
|
conditions and on expressions.
|
2005-03-02 10:38:25 +01:00
|
|
|
|
|
|
|
All equality predicates of the form field1=field2 contained in a
|
2005-02-08 23:50:45 +01:00
|
|
|
conjunction are substituted for a sequence of items of this class.
|
|
|
|
An item of this class Item_equal(f1,f2,...fk) represents a
|
2004-02-19 07:21:37 +01:00
|
|
|
multiple equality f1=f2=...=fk.
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
If a conjunction contains predicates f1=f2 and f2=f3, a new item of
|
2004-02-19 07:21:37 +01:00
|
|
|
this class is created Item_equal(f1,f2,f3) representing the multiple
|
|
|
|
equality f1=f2=f3 that substitutes the above equality predicates in
|
2005-02-08 23:50:45 +01:00
|
|
|
the conjunction.
|
|
|
|
A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be
|
2004-02-19 07:21:37 +01:00
|
|
|
substituted for the item representing the same multiple equality
|
|
|
|
f1=f2=f3.
|
2005-02-08 23:50:45 +01:00
|
|
|
An item Item_equal(f1,f2) can appear instead of a conjunction of
|
2004-02-19 07:21:37 +01:00
|
|
|
f2=f1 and f1=f2, or instead of just the predicate f1=f2.
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
An item of the class Item_equal inherits equalities from outer
|
2004-02-19 07:21:37 +01:00
|
|
|
conjunctive levels.
|
|
|
|
|
|
|
|
Suppose we have a where condition of the following form:
|
|
|
|
WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)).
|
|
|
|
In this case:
|
|
|
|
f1=f2 will be substituted for Item_equal(f1,f2);
|
|
|
|
f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5);
|
|
|
|
f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5);
|
|
|
|
|
|
|
|
An object of the class Item_equal can contain an optional constant
|
2005-02-08 23:50:45 +01:00
|
|
|
item c. Then it represents a multiple equality of the form
|
2004-02-19 07:21:37 +01:00
|
|
|
c=f1=...=fk.
|
|
|
|
|
|
|
|
Objects of the class Item_equal are used for the following:
|
|
|
|
|
|
|
|
1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any
|
|
|
|
pair of tables ti and tj as joined by an equi-condition.
|
|
|
|
Thus it provide us with additional access paths from table to table.
|
|
|
|
|
|
|
|
2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new
|
|
|
|
SARGable predicates:
|
|
|
|
f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj).
|
|
|
|
It also can give us additional index scans and can allow us to
|
|
|
|
improve selectivity estimates.
|
|
|
|
|
|
|
|
3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the
|
|
|
|
selected execution plan for the query: if table ti is accessed
|
|
|
|
before the table tj then in any predicate P in the where condition
|
2005-02-08 23:50:45 +01:00
|
|
|
the occurrence of tj.fj is substituted for ti.fi. This can allow
|
2004-02-19 07:21:37 +01:00
|
|
|
an evaluation of the predicate at an earlier step.
|
|
|
|
|
|
|
|
When feature 1 is supported they say that join transitive closure
|
|
|
|
is employed.
|
|
|
|
When feature 2 is supported they say that search argument transitive
|
|
|
|
closure is employed.
|
|
|
|
Both features are usually supported by preprocessing original query and
|
|
|
|
adding additional predicates.
|
|
|
|
We do not just add predicates, we rather dynamically replace some
|
|
|
|
predicates that can not be used to access tables in the investigated
|
|
|
|
plan for those, obtained by substitution of some fields for equal fields,
|
|
|
|
that can be used.
|
2005-03-03 15:38:59 +01:00
|
|
|
|
|
|
|
Prepared Statements/Stored Procedures note: instances of class
|
|
|
|
Item_equal are created only at the time a PS/SP is executed and
|
|
|
|
are deleted in the end of execution. All changes made to these
|
|
|
|
objects need not be registered in the list of changes of the parse
|
|
|
|
tree and do not harm PS/SP re-execution.
|
2006-01-11 20:49:43 +01:00
|
|
|
|
|
|
|
Item equal objects are employed only at the optimize phase. Usually they are
|
|
|
|
not supposed to be evaluated. Yet in some cases we call the method val_int()
|
|
|
|
for them. We have to take care of restricting the predicate such an
|
|
|
|
object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik.
|
2004-02-19 07:21:37 +01:00
|
|
|
*/
|
|
|
|
|
2003-11-27 02:23:52 +01:00
|
|
|
class Item_equal: public Item_bool_func
|
|
|
|
{
|
|
|
|
List<Item_field> fields; /* list of equal field items */
|
|
|
|
Item *const_item; /* optional constant item equal to fields items */
|
|
|
|
cmp_item *eval_item;
|
2009-12-04 18:58:40 +01:00
|
|
|
Arg_comparator cmp;
|
2003-11-27 02:23:52 +01:00
|
|
|
bool cond_false;
|
2009-12-04 18:58:40 +01:00
|
|
|
bool compare_as_dates;
|
2003-11-27 02:23:52 +01:00
|
|
|
public:
|
|
|
|
inline Item_equal()
|
|
|
|
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
|
|
|
|
{ const_item_cache=0 ;}
|
|
|
|
Item_equal(Item_field *f1, Item_field *f2);
|
|
|
|
Item_equal(Item *c, Item_field *f);
|
|
|
|
Item_equal(Item_equal *item_equal);
|
|
|
|
inline Item* get_const() { return const_item; }
|
2009-12-04 18:58:40 +01:00
|
|
|
void compare_const(Item *c);
|
|
|
|
void add(Item *c, Item_field *f);
|
2003-11-27 02:23:52 +01:00
|
|
|
void add(Item *c);
|
|
|
|
void add(Item_field *f);
|
2004-02-19 07:21:37 +01:00
|
|
|
uint members();
|
2003-11-27 02:23:52 +01:00
|
|
|
bool contains(Field *field);
|
|
|
|
Item_field* get_first() { return fields.head(); }
|
|
|
|
void merge(Item_equal *item);
|
2006-04-04 06:02:40 +02:00
|
|
|
void update_const();
|
2003-11-27 02:23:52 +01:00
|
|
|
enum Functype functype() const { return MULT_EQUAL_FUNC; }
|
|
|
|
longlong val_int();
|
|
|
|
const char *func_name() const { return "multiple equal"; }
|
|
|
|
optimize_type select_optimize() const { return OPTIMIZE_EQUAL; }
|
2010-03-14 17:01:45 +01:00
|
|
|
void sort(Item_field_cmpfunc compare, void *arg);
|
2003-11-27 02:23:52 +01:00
|
|
|
friend class Item_equal_iterator;
|
|
|
|
void fix_length_and_dec();
|
2005-07-01 06:05:42 +02:00
|
|
|
bool fix_fields(THD *thd, Item **ref);
|
2003-11-27 02:23:52 +01:00
|
|
|
void update_used_tables();
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
|
|
|
|
Item *transform(Item_transformer transformer, uchar *arg);
|
2008-02-22 11:30:33 +01:00
|
|
|
virtual void print(String *str, enum_query_type query_type);
|
2004-02-20 02:12:31 +01:00
|
|
|
CHARSET_INFO *compare_collation()
|
|
|
|
{ return fields.head()->collation.collation; }
|
2003-11-27 02:23:52 +01:00
|
|
|
};
|
|
|
|
|
2004-10-26 08:08:55 +02:00
|
|
|
class COND_EQUAL: public Sql_alloc
|
2003-11-27 02:23:52 +01:00
|
|
|
{
|
|
|
|
public:
|
2004-02-19 07:21:37 +01:00
|
|
|
uint max_members; /* max number of members the current level
|
|
|
|
list and all lower level lists */
|
|
|
|
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
|
|
|
|
List<Item_equal> current_level; /* list of multiple equalities of
|
|
|
|
the current and level */
|
|
|
|
COND_EQUAL()
|
|
|
|
{
|
|
|
|
upper_levels= 0;
|
|
|
|
}
|
2003-11-27 02:23:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-11-29 22:47:50 +01:00
|
|
|
class Item_equal_iterator : public List_iterator_fast<Item_field>
|
2003-11-27 02:23:52 +01:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
inline Item_equal_iterator(Item_equal &item_equal)
|
|
|
|
:List_iterator_fast<Item_field> (item_equal.fields)
|
|
|
|
{}
|
|
|
|
inline Item_field* operator++(int)
|
|
|
|
{
|
|
|
|
Item_field *item= (*(List_iterator_fast<Item_field> *) this)++;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
inline void rewind(void)
|
|
|
|
{
|
|
|
|
List_iterator_fast<Item_field>::rewind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_cond_and :public Item_cond
|
|
|
|
{
|
|
|
|
public:
|
2004-02-19 07:21:37 +01:00
|
|
|
COND_EQUAL cond_equal; /* contains list of Item_equal objects for
|
|
|
|
the current and level and reference
|
|
|
|
to multiple equalities of upper and levels */
|
2000-07-31 21:29:14 +02:00
|
|
|
Item_cond_and() :Item_cond() {}
|
|
|
|
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
|
2004-01-19 16:53:25 +01:00
|
|
|
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
|
2006-12-14 23:51:37 +01:00
|
|
|
Item_cond_and(List<Item> &list_arg): Item_cond(list_arg) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Functype functype() const { return COND_AND_FUNC; }
|
|
|
|
longlong val_int();
|
|
|
|
const char *func_name() const { return "and"; }
|
2005-03-13 16:34:40 +01:00
|
|
|
table_map not_null_tables() const
|
|
|
|
{ return abort_on_null ? not_null_tables_cache: and_tables_cache; }
|
2003-09-02 18:56:55 +02:00
|
|
|
Item* copy_andor_structure(THD *thd)
|
|
|
|
{
|
|
|
|
Item_cond_and *item;
|
2004-02-05 18:14:48 +01:00
|
|
|
if ((item= new Item_cond_and(thd, this)))
|
2003-09-02 18:56:55 +02:00
|
|
|
item->copy_andor_arguments(thd, this);
|
|
|
|
return item;
|
|
|
|
}
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
Bug#30237 (Performance regression in boolean expressions)
This is a performance bug, related to the parsing or 'OR' and 'AND' boolean
expressions.
Let N be the number of expressions involved in a OR (respectively AND).
When N=1
For example, "select 1" involve only 1 term: there is no OR operator.
In 4.0 and 4.1, parsing expressions not involving OR had no overhead.
In 5.0, parsing adds some overhead, with Select->expr_list.
With this patch, the overhead introduced in 5.0 has been removed,
so that performances for N=1 should be identical to the 4.0 performances,
which are optimal (there is no code executed at all)
The overhead in 5.0 was in fact affecting significantly some operations.
For example, loading 1 Million rows into a table with INSERTs,
for a table that has 100 columns, leads to parsing 100 Millions of
expressions, which means that the overhead related to Select->expr_list
is executed 100 Million times ...
Considering that N=1 is by far the most probable expression,
this case should be optimal.
When N=2
For example, "select a OR b" involves 2 terms in the OR operator.
In 4.0 and 4.1, parsing expressions involving 2 terms created 1 Item_cond_or
node, which is the expected result.
In 5.0, parsing these expression also produced 1 node, but with some extra
overhead related to Select->expr_list : creating 1 list in Select->expr_list
and another in Item_cond::list is inefficient.
With this patch, the overhead introduced in 5.0 has been removed
so that performances for N=2 should be identical to the 4.0 performances.
Note that the memory allocation uses the new (thd->mem_root) syntax
directly.
The cost of "is_cond_or" is estimated to be neglectable: the real problem
of the performance degradation comes from unneeded memory allocations.
When N>=3
For example, "select a OR b OR c ...", which involves 3 or more terms.
In 4.0 and 4.1, the parser had no significant cost overhead, but produced
an Item tree which is difficult to evaluate / optimize during runtime.
In 5.0, the parser produces a better Item tree, using the Item_cond
constructor that accepts a list of children directly, but at an extra cost
related to Select->expr_list.
With this patch, the code is implemented to take the best of the two
implementations:
- there is no overhead with Select->expr_list
- the Item tree generated is optimized and flattened.
This is achieved by adding children nodes into the Item tree directly,
with Item_cond::add(), which avoids the need for temporary lists and memory
allocation
Note that this patch also provide an extra optimization, that the previous
code in 5.0 did not provide: expressions are flattened in the Item tree,
based on what the expression already parsed is, and not based on the order
in which rules are reduced.
For example : "(a OR b) OR c", "a OR (b OR c)" would both be represented
with 2 Item_cond_or nodes before this patch, and with 1 node only with this
patch. The logic used is based on the mathematical properties of the OR
operator (it's associative), and produces a simpler tree.
2007-08-22 19:05:35 +02:00
|
|
|
inline bool is_cond_and(Item *item)
|
|
|
|
{
|
|
|
|
if (item->type() != Item::COND_ITEM)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Item_cond *cond_item= (Item_cond*) item;
|
|
|
|
return (cond_item->functype() == Item_func::COND_AND_FUNC);
|
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
class Item_cond_or :public Item_cond
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_cond_or() :Item_cond() {}
|
|
|
|
Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
|
2004-01-19 16:53:25 +01:00
|
|
|
Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {}
|
2006-12-14 23:51:37 +01:00
|
|
|
Item_cond_or(List<Item> &list_arg): Item_cond(list_arg) {}
|
2000-07-31 21:29:14 +02:00
|
|
|
enum Functype functype() const { return COND_OR_FUNC; }
|
|
|
|
longlong val_int();
|
|
|
|
const char *func_name() const { return "or"; }
|
2003-06-26 04:38:19 +02:00
|
|
|
table_map not_null_tables() const { return and_tables_cache; }
|
2003-09-02 18:56:55 +02:00
|
|
|
Item* copy_andor_structure(THD *thd)
|
|
|
|
{
|
|
|
|
Item_cond_or *item;
|
2004-02-05 18:14:48 +01:00
|
|
|
if ((item= new Item_cond_or(thd, this)))
|
2003-09-02 18:56:55 +02:00
|
|
|
item->copy_andor_arguments(thd, this);
|
|
|
|
return item;
|
|
|
|
}
|
2004-03-17 13:26:26 +01:00
|
|
|
Item *neg_transformer(THD *thd);
|
2000-07-31 21:29:14 +02:00
|
|
|
};
|
|
|
|
|
Bug#30237 (Performance regression in boolean expressions)
This is a performance bug, related to the parsing or 'OR' and 'AND' boolean
expressions.
Let N be the number of expressions involved in a OR (respectively AND).
When N=1
For example, "select 1" involve only 1 term: there is no OR operator.
In 4.0 and 4.1, parsing expressions not involving OR had no overhead.
In 5.0, parsing adds some overhead, with Select->expr_list.
With this patch, the overhead introduced in 5.0 has been removed,
so that performances for N=1 should be identical to the 4.0 performances,
which are optimal (there is no code executed at all)
The overhead in 5.0 was in fact affecting significantly some operations.
For example, loading 1 Million rows into a table with INSERTs,
for a table that has 100 columns, leads to parsing 100 Millions of
expressions, which means that the overhead related to Select->expr_list
is executed 100 Million times ...
Considering that N=1 is by far the most probable expression,
this case should be optimal.
When N=2
For example, "select a OR b" involves 2 terms in the OR operator.
In 4.0 and 4.1, parsing expressions involving 2 terms created 1 Item_cond_or
node, which is the expected result.
In 5.0, parsing these expression also produced 1 node, but with some extra
overhead related to Select->expr_list : creating 1 list in Select->expr_list
and another in Item_cond::list is inefficient.
With this patch, the overhead introduced in 5.0 has been removed
so that performances for N=2 should be identical to the 4.0 performances.
Note that the memory allocation uses the new (thd->mem_root) syntax
directly.
The cost of "is_cond_or" is estimated to be neglectable: the real problem
of the performance degradation comes from unneeded memory allocations.
When N>=3
For example, "select a OR b OR c ...", which involves 3 or more terms.
In 4.0 and 4.1, the parser had no significant cost overhead, but produced
an Item tree which is difficult to evaluate / optimize during runtime.
In 5.0, the parser produces a better Item tree, using the Item_cond
constructor that accepts a list of children directly, but at an extra cost
related to Select->expr_list.
With this patch, the code is implemented to take the best of the two
implementations:
- there is no overhead with Select->expr_list
- the Item tree generated is optimized and flattened.
This is achieved by adding children nodes into the Item tree directly,
with Item_cond::add(), which avoids the need for temporary lists and memory
allocation
Note that this patch also provide an extra optimization, that the previous
code in 5.0 did not provide: expressions are flattened in the Item tree,
based on what the expression already parsed is, and not based on the order
in which rules are reduced.
For example : "(a OR b) OR c", "a OR (b OR c)" would both be represented
with 2 Item_cond_or nodes before this patch, and with 1 node only with this
patch. The logic used is based on the mathematical properties of the OR
operator (it's associative), and produces a simpler tree.
2007-08-22 19:05:35 +02:00
|
|
|
inline bool is_cond_or(Item *item)
|
|
|
|
{
|
|
|
|
if (item->type() != Item::COND_ITEM)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Item_cond *cond_item= (Item_cond*) item;
|
|
|
|
return (cond_item->functype() == Item_func::COND_OR_FUNC);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-08-05 16:29:09 +02:00
|
|
|
/*
|
2005-02-08 23:50:45 +01:00
|
|
|
XOR is Item_cond, not an Item_int_func because we could like to
|
2003-08-05 16:29:09 +02:00
|
|
|
optimize (a XOR b) later on. It's low prio, though
|
|
|
|
*/
|
2003-08-11 21:44:43 +02:00
|
|
|
|
2002-08-30 11:40:40 +02:00
|
|
|
class Item_cond_xor :public Item_cond
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Item_cond_xor() :Item_cond() {}
|
|
|
|
Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {}
|
|
|
|
enum Functype functype() const { return COND_XOR_FUNC; }
|
2003-08-05 16:29:09 +02:00
|
|
|
/* TODO: remove the next line when implementing XOR optimization */
|
|
|
|
enum Type type() const { return FUNC_ITEM; }
|
2002-08-30 11:40:40 +02:00
|
|
|
longlong val_int();
|
|
|
|
const char *func_name() const { return "xor"; }
|
2005-03-13 16:34:40 +01:00
|
|
|
void top_level_item() {}
|
2002-08-30 11:40:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
/* Some useful inline functions */
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2004-04-03 10:13:51 +02:00
|
|
|
inline Item *and_conds(Item *a, Item *b)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
if (!b) return a;
|
|
|
|
if (!a) return b;
|
2004-04-03 10:13:51 +02:00
|
|
|
return new Item_cond_and(a, b);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2002-06-29 15:25:09 +02:00
|
|
|
|
2010-03-31 16:05:33 +02:00
|
|
|
|
2002-11-21 14:56:48 +01:00
|
|
|
Item *and_expressions(Item *a, Item *b, Item **org_item);
|
2009-11-02 13:24:07 +01:00
|
|
|
|
2010-03-31 16:05:33 +02:00
|
|
|
longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
|
|
|
|
Item *warn_item, bool *is_null);
|
|
|
|
|
|
|
|
|
2009-11-06 15:20:27 +01:00
|
|
|
bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
|
2009-11-02 13:24:07 +01:00
|
|
|
const char *warn_name, MYSQL_TIME *l_time);
|
2010-03-31 16:05:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
These need definitions from this file but the variables are defined
|
|
|
|
in mysqld.h. The variables really belong in this component, but for
|
|
|
|
the time being we leave them in mysqld.cc to avoid merge problems.
|
|
|
|
*/
|
|
|
|
extern Eq_creator eq_creator;
|
|
|
|
extern Ne_creator ne_creator;
|
|
|
|
extern Gt_creator gt_creator;
|
|
|
|
extern Lt_creator lt_creator;
|
|
|
|
extern Ge_creator ge_creator;
|
|
|
|
extern Le_creator le_creator;
|
|
|
|
|
2009-09-23 23:32:31 +02:00
|
|
|
#endif /* ITEM_CMPFUNC_INCLUDED */
|