1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Manual merge from mysql-trunk-merge.

Conflicts:
  - extra/comp_err.c
  - mysql-test/collections/default.experimental
  - mysql-test/r/archive.result
  - mysql-test/r/select.result
  - mysql-test/suite/binlog/r/binlog_unsafe.result
  - mysql-test/suite/binlog/t/binlog_unsafe.test
  - mysql-test/suite/rpl/t/disabled.def
  - mysql-test/t/archive.test
  - mysql-test/t/select.test
  - sql/item.cc
  - sql/item.h
  - sql/item_timefunc.cc
  - sql/sql_base.cc
  - sql/sql_delete.cc
  - sql/sql_load.cc
  - sql/sql_partition.cc
  - sql/sql_table.cc
  - storage/innobase/handler/ha_innodb.cc
  - vio/vio.c
This commit is contained in:
Alexander Nozdrin
2009-12-12 23:38:59 +03:00
221 changed files with 5385 additions and 1584 deletions

View File

@@ -30,6 +30,9 @@
#include "sql_select.h"
static bool convert_constant_item(THD *, Item_field *, Item **);
static longlong
get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null);
static Item_result item_store_type(Item_result a, Item *item,
my_bool unsigned_flag)
@@ -533,11 +536,12 @@ void Item_bool_func2::fix_length_and_dec()
}
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
{
owner= item;
func= comparator_matrix[type]
[test(owner->functype() == Item_func::EQUAL_FUNC)];
[is_owner_equal_func()];
switch (type) {
case ROW_RESULT:
{
@@ -557,7 +561,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1;
}
if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)))
if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i),
set_null))
return 1;
}
break;
@@ -571,7 +576,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
if (cmp_collation.set((*a)->collation, (*b)->collation) ||
cmp_collation.derivation == DERIVATION_NONE)
{
my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
my_coll_agg_error((*a)->collation, (*b)->collation,
owner->func_name());
return 1;
}
if (cmp_collation.collation == &my_charset_bin)
@@ -785,15 +791,21 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
if (cmp_type != CMP_DATE_DFLT)
{
THD *thd= current_thd;
/*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE
for the current thread but it still may change during the execution.
Don't use cache while in the context analysis mode only (i.e. for
EXPLAIN/CREATE VIEW and similar queries). Cache is useless in such
cases and can cause problems. For example evaluating subqueries can
confuse storage engines since in context analysis mode tables
aren't locked.
*/
if (cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() &&
if (!thd->is_context_analysis_only() &&
cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() &&
(str_arg->type() != Item::FUNC_ITEM ||
((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC))
{
THD *thd= current_thd;
ulonglong value;
bool error;
String tmp, *str_val= 0;
@@ -876,7 +888,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
}
int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **a2,
Item_result type)
{
@@ -886,6 +898,8 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
owner= owner_arg;
a= a1;
b= a2;
owner= owner_arg;
thd= current_thd;
if ((cmp_type= can_compare_as_dates(*a, *b, &const_value)))
{
@@ -916,9 +930,10 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
b= (Item **)&b_cache;
}
}
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
is_nulls_eq= is_owner_equal_func();
func= &Arg_comparator::compare_datetime;
get_value_func= &get_datetime_value;
get_value_a_func= &get_datetime_value;
get_value_b_func= &get_datetime_value;
return 0;
}
else if (type == STRING_RESULT && (*a)->field_type() == MYSQL_TYPE_TIME &&
@@ -927,9 +942,10 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
/* Compare TIME values as integers. */
a_cache= 0;
b_cache= 0;
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
is_nulls_eq= is_owner_equal_func();
func= &Arg_comparator::compare_datetime;
get_value_func= &get_time_value;
get_value_a_func= &get_time_value;
get_value_b_func= &get_time_value;
return 0;
}
else if (type == STRING_RESULT &&
@@ -938,9 +954,42 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
{
DTCollation coll;
coll.set((*a)->collation.collation);
if (agg_item_set_converter(coll, owner_arg->func_name(),
if (agg_item_set_converter(coll, owner->func_name(),
b, 1, MY_COLL_CMP_CONV, 1))
return 1;
} else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR ||
(*b)->field_type() == MYSQL_TYPE_YEAR))
{
is_nulls_eq= is_owner_equal_func();
year_as_datetime= FALSE;
if ((*a)->is_datetime())
{
year_as_datetime= TRUE;
get_value_a_func= &get_datetime_value;
} else if ((*a)->field_type() == MYSQL_TYPE_YEAR)
get_value_a_func= &get_year_value;
else
{
/*
Because convert_constant_item is called only for EXECUTE in PS mode
the value of get_value_x_func set in PREPARE might be not
valid for EXECUTE.
*/
get_value_a_func= NULL;
}
if ((*b)->is_datetime())
{
year_as_datetime= TRUE;
get_value_b_func= &get_datetime_value;
} else if ((*b)->field_type() == MYSQL_TYPE_YEAR)
get_value_b_func= &get_year_value;
else
get_value_b_func= NULL;
func= &Arg_comparator::compare_year;
return 0;
}
a= cache_converted_constant(thd, a, &a_cache, type);
@@ -983,11 +1032,11 @@ Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value,
}
void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **b1)
{
thd= current_thd;
/* A caller will handle null values by itself. */
owner= NULL;
owner= owner_arg;
a= a1;
b= b1;
a_type= (*a)->field_type();
@@ -996,7 +1045,8 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
b_cache= 0;
is_nulls_eq= FALSE;
func= &Arg_comparator::compare_datetime;
get_value_func= &get_datetime_value;
get_value_a_func= &get_datetime_value;
get_value_b_func= &get_datetime_value;
}
@@ -1096,6 +1146,51 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
return value;
}
/*
Retrieves YEAR value of 19XX form from given item.
SYNOPSIS
get_year_value()
thd thread handle
item_arg [in/out] item to retrieve YEAR value from
cache_arg [in/out] pointer to place to store the caching item to
warn_item [in] item for issuing the conversion warning
is_null [out] TRUE <=> the item_arg is null
DESCRIPTION
Retrieves the YEAR value of 19XX form from given item for comparison by the
compare_year() function.
RETURN
obtained value
*/
static longlong
get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null)
{
longlong value= 0;
Item *item= **item_arg;
value= item->val_int();
*is_null= item->null_value;
if (*is_null)
return ~(ulonglong) 0;
/*
Coerce value to the 19XX form in order to correctly compare
YEAR(2) & YEAR(4) types.
*/
if (value < 70)
value+= 100;
if (value <= 1900)
value+= 1900;
return value;
}
/*
Compare items values as dates.
@@ -1128,25 +1223,25 @@ int Arg_comparator::compare_datetime()
longlong a_value, b_value;
/* Get DATE/DATETIME/TIME value of the 'a' item. */
a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null);
a_value= (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null);
if (!is_nulls_eq && a_is_null)
{
if (owner)
if (set_null)
owner->null_value= 1;
return -1;
}
/* Get DATE/DATETIME/TIME value of the 'b' item. */
b_value= (*get_value_func)(thd, &b, &b_cache, *a, &b_is_null);
b_value= (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null);
if (a_is_null || b_is_null)
{
if (owner)
if (set_null)
owner->null_value= is_nulls_eq ? 0 : 1;
return is_nulls_eq ? (a_is_null == b_is_null) : -1;
}
/* Here we have two not-NULL values. */
if (owner)
if (set_null)
owner->null_value= 0;
/* Compare values. */
@@ -1159,15 +1254,17 @@ int Arg_comparator::compare_datetime()
int Arg_comparator::compare_string()
{
String *res1,*res2;
if ((res1= (*a)->val_str(&owner->tmp_value1)))
if ((res1= (*a)->val_str(&value1)))
{
if ((res2= (*b)->val_str(&owner->tmp_value2)))
if ((res2= (*b)->val_str(&value2)))
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
return sortcmp(res1,res2,cmp_collation.collation);
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1186,18 +1283,20 @@ int Arg_comparator::compare_string()
int Arg_comparator::compare_binary_string()
{
String *res1,*res2;
if ((res1= (*a)->val_str(&owner->tmp_value1)))
if ((res1= (*a)->val_str(&value1)))
{
if ((res2= (*b)->val_str(&owner->tmp_value2)))
if ((res2= (*b)->val_str(&value2)))
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
uint res1_length= res1->length();
uint res2_length= res2->length();
int cmp= memcmp(res1->ptr(), res2->ptr(), min(res1_length,res2_length));
return cmp ? cmp : (int) (res1_length - res2_length);
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1210,8 +1309,8 @@ int Arg_comparator::compare_binary_string()
int Arg_comparator::compare_e_string()
{
String *res1,*res2;
res1= (*a)->val_str(&owner->tmp_value1);
res2= (*b)->val_str(&owner->tmp_value2);
res1= (*a)->val_str(&value1);
res2= (*b)->val_str(&value2);
if (!res1 || !res2)
return test(res1 == res2);
return test(sortcmp(res1, res2, cmp_collation.collation) == 0);
@@ -1221,8 +1320,8 @@ int Arg_comparator::compare_e_string()
int Arg_comparator::compare_e_binary_string()
{
String *res1,*res2;
res1= (*a)->val_str(&owner->tmp_value1);
res2= (*b)->val_str(&owner->tmp_value2);
res1= (*a)->val_str(&value1);
res2= (*b)->val_str(&value2);
if (!res1 || !res2)
return test(res1 == res2);
return test(stringcmp(res1, res2) == 0);
@@ -1243,13 +1342,15 @@ int Arg_comparator::compare_real()
val2= (*b)->val_real();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1263,11 +1364,13 @@ int Arg_comparator::compare_decimal()
my_decimal *val2= (*b)->val_decimal(&value2);
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
return my_decimal_cmp(val1, val2);
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1305,7 +1408,8 @@ int Arg_comparator::compare_real_fixed()
val2= (*b)->val_real();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (val1 == val2 || fabs(val1 - val2) < precision)
return 0;
if (val1 < val2)
@@ -1313,7 +1417,8 @@ int Arg_comparator::compare_real_fixed()
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1336,13 +1441,15 @@ int Arg_comparator::compare_int_signed()
longlong val2= (*b)->val_int();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1359,13 +1466,15 @@ int Arg_comparator::compare_int_unsigned()
ulonglong val2= (*b)->val_int();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1382,7 +1491,8 @@ int Arg_comparator::compare_int_signed_unsigned()
ulonglong uval2= (ulonglong)(*b)->val_int();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (sval1 < 0 || (ulonglong)sval1 < uval2)
return -1;
if ((ulonglong)sval1 == uval2)
@@ -1390,7 +1500,8 @@ int Arg_comparator::compare_int_signed_unsigned()
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1407,7 +1518,8 @@ int Arg_comparator::compare_int_unsigned_signed()
longlong sval2= (*b)->val_int();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (set_null)
owner->null_value= 0;
if (sval2 < 0)
return 1;
if (uval1 < (ulonglong)sval2)
@@ -1417,7 +1529,8 @@ int Arg_comparator::compare_int_unsigned_signed()
return 1;
}
}
owner->null_value= 1;
if (set_null)
owner->null_value= 1;
return -1;
}
@@ -1453,10 +1566,11 @@ int Arg_comparator::compare_row()
for (uint i= 0; i<n; i++)
{
res= comparators[i].compare();
if (owner->null_value)
/* Aggregate functions don't need special null handling. */
if (owner->null_value && owner->type() == Item::FUNC_ITEM)
{
// NULL was compared
switch (owner->functype()) {
switch (((Item_func*)owner)->functype()) {
case Item_func::NE_FUNC:
break; // NE never aborts on NULL even if abort_on_null is set
case Item_func::LT_FUNC:
@@ -1465,7 +1579,7 @@ int Arg_comparator::compare_row()
case Item_func::GE_FUNC:
return -1; // <, <=, > and >= always fail on NULL
default: // EQ_FUNC
if (owner->abort_on_null)
if (((Item_bool_func2*)owner)->abort_on_null)
return -1; // We do not need correct NULL returning
}
was_null= 1;
@@ -1502,6 +1616,67 @@ int Arg_comparator::compare_e_row()
}
/**
Compare values as YEAR.
@details
Compare items as YEAR for EQUAL_FUNC and for other comparison functions.
The YEAR values of form 19XX are obtained with help of the get_year_value()
function.
If one of arguments is of DATE/DATETIME type its value is obtained
with help of the get_datetime_value function. In this case YEAR values
prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00
DATETIME form.
If an argument type neither YEAR nor DATE/DATEIME then val_int function
is used to obtain value for comparison.
RETURN
If is_nulls_eq is TRUE:
1 if items are equal or both are null
0 otherwise
If is_nulls_eq is FALSE:
-1 a < b
0 a == b or at least one of items is null
1 a > b
See the table:
is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1|
*/
int Arg_comparator::compare_year()
{
bool a_is_null, b_is_null;
ulonglong val1= get_value_a_func ?
(*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) :
(*a)->val_int();
ulonglong val2= get_value_b_func ?
(*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) :
(*b)->val_int();
if (!(*a)->null_value)
{
if (!(*b)->null_value)
{
if (set_null)
owner->null_value= 0;
/* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */
if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime)
val1*= 10000000000LL;
if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime)
val2*= 10000000000LL;
if (val1 < val2) return is_nulls_eq ? 0 : -1;
if (val1 == val2) return is_nulls_eq ? 1 : 0;
return is_nulls_eq ? 0 : 1;
}
}
if (set_null)
owner->null_value= is_nulls_eq ? 0 : 1;
return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0;
}
void Item_func_truth::fix_length_and_dec()
{
maybe_null= 0;
@@ -1789,8 +1964,8 @@ longlong Item_func_lt::val_int()
longlong Item_func_strcmp::val_int()
{
DBUG_ASSERT(fixed == 1);
String *a=args[0]->val_str(&tmp_value1);
String *b=args[1]->val_str(&tmp_value2);
String *a=args[0]->val_str(&cmp.value1);
String *b=args[1]->val_str(&cmp.value2);
if (!a || !b)
{
null_value=1;
@@ -2073,8 +2248,8 @@ void Item_func_between::fix_length_and_dec()
if (compare_as_dates)
{
ge_cmp.set_datetime_cmp_func(args, args + 1);
le_cmp.set_datetime_cmp_func(args, args + 2);
ge_cmp.set_datetime_cmp_func(this, args, args + 1);
le_cmp.set_datetime_cmp_func(this, args, args + 2);
}
else if (time_items_found == 3)
{
@@ -4402,13 +4577,13 @@ void Item_func_isnotnull::print(String *str, enum_query_type query_type)
longlong Item_func_like::val_int()
{
DBUG_ASSERT(fixed == 1);
String* res = args[0]->val_str(&tmp_value1);
String* res = args[0]->val_str(&cmp.value1);
if (args[0]->null_value)
{
null_value=1;
return 0;
}
String* res2 = args[1]->val_str(&tmp_value2);
String* res2 = args[1]->val_str(&cmp.value2);
if (args[1]->null_value)
{
null_value=1;
@@ -4432,7 +4607,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
{
if (args[1]->const_item())
{
String* res2= args[1]->val_str((String *)&tmp_value2);
String* res2= args[1]->val_str((String *)&cmp.value2);
if (!res2)
return OPTIMIZE_NONE;
@@ -4463,7 +4638,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (escape_item->const_item())
{
/* If we are on execution stage */
String *escape_str= escape_item->val_str(&tmp_value1);
String *escape_str= escape_item->val_str(&cmp.value1);
if (escape_str)
{
if (escape_used_in_parsing && (
@@ -4518,7 +4693,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
!(specialflag & SPECIAL_NO_NEW_FUNC))
{
String* res2 = args[1]->val_str(&tmp_value2);
String* res2 = args[1]->val_str(&cmp.value2);
if (!res2)
return FALSE; // Null argument