diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 9ecc062d645..e2e60c43f58 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -22,7 +22,7 @@ #endif #include "mysql_priv.h" -#include "slave.h" // for wait_for_master_pos +#include "slave.h" // for wait_for_master_pos #include <m_ctype.h> #include <hash.h> #include <time.h> @@ -31,7 +31,9 @@ #include <zlib.h> #endif -static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) + +static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, + const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->name,c1.derivation_name(), @@ -39,6 +41,7 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fnam fname); } + static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3, @@ -51,11 +54,12 @@ static void my_coll_agg_error(DTCollation &c1, fname); } -static void my_coll_agg_error(Item** args, uint ac, const char *fname) + +static void my_coll_agg_error(Item** args, uint count, const char *fname) { - if (2 == ac) + if (count == 2) my_coll_agg_error(args[0]->collation, args[1]->collation, fname); - else if (3 == ac) + else if (count == 3) my_coll_agg_error(args[0]->collation, args[1]->collation, args[2]->collation, @@ -64,30 +68,32 @@ static void my_coll_agg_error(Item** args, uint ac, const char *fname) my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname); } -bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint ac) + +bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count) { uint i; c.set(av[0]->collation); - for (i= 1; i < ac; i++) + for (i= 1; i < count; i++) { if (c.aggregate(av[i]->collation)) { - my_coll_agg_error(av, ac, func_name()); + my_coll_agg_error(av, count, func_name()); return TRUE; } } return FALSE; } + bool Item_func::agg_arg_collations_for_comparison(DTCollation &c, - Item **av, uint ac) + Item **av, uint count) { - if (agg_arg_collations(c, av, ac)) + if (agg_arg_collations(c, av, count)) return TRUE; if (c.derivation == DERIVATION_NONE) { - my_coll_agg_error(av, ac, func_name()); + my_coll_agg_error(av, count, func_name()); return TRUE; } return FALSE; @@ -102,6 +108,7 @@ eval_const_cond(COND *cond) return ((Item_func*) cond)->val_int() ? TRUE : FALSE; } + void Item_func::set_arguments(List<Item> &list) { allowed_arg_cols= 1; @@ -586,6 +593,7 @@ double Item_func_neg::val() return -value; } + longlong Item_func_neg::val_int() { longlong value=args[0]->val_int(); @@ -593,14 +601,32 @@ longlong Item_func_neg::val_int() return -value; } + void Item_func_neg::fix_length_and_dec() { decimals=args[0]->decimals; max_length=args[0]->max_length; - hybrid_type= args[0]->result_type() == INT_RESULT && !args[0]->unsigned_flag ? - INT_RESULT : REAL_RESULT; + hybrid_type= REAL_RESULT; + if (args[0]->result_type() == INT_RESULT) + { + /* + If this is in integer context keep the context as integer + (This is how multiplication and other integer functions works) + + We must however do a special case in the case where the argument + is a unsigned bigint constant as in this case the only safe + number to convert in integer context is 9223372036854775808. + (This is needed because the lex parser doesn't anymore handle + signed integers) + */ + if (args[0]->type() != INT_ITEM || + ((ulonglong) ((Item_uint*) args[0])->value <= + (ulonglong) LONGLONG_MIN)) + hybrid_type= INT_RESULT; + } } + double Item_func_abs::val() { double value=args[0]->val(); @@ -608,6 +634,7 @@ double Item_func_abs::val() return fabs(value); } + longlong Item_func_abs::val_int() { longlong value=args[0]->val_int(); @@ -615,13 +642,20 @@ longlong Item_func_abs::val_int() return value >= 0 ? value : -value; } + void Item_func_abs::fix_length_and_dec() { decimals=args[0]->decimals; max_length=args[0]->max_length; - hybrid_type= args[0]->result_type() == INT_RESULT ? INT_RESULT : REAL_RESULT; + hybrid_type= REAL_RESULT; + if (args[0]->result_type() == INT_RESULT) + { + hybrid_type= INT_RESULT; + unsigned_flag= 1; + } } + /* Gateway to natural LOG function */ double Item_func_ln::val() { @@ -1051,6 +1085,7 @@ longlong Item_func_crc32::val_int() return (longlong) crc32(0L, (Bytef*)res->ptr(), res->length()); } + longlong Item_func_uncompressed_length::val_int() { String *res= args[0]->val_str(&value); @@ -1063,9 +1098,9 @@ longlong Item_func_uncompressed_length::val_int() if (res->is_empty()) return 0; return uint4korr(res->c_ptr()) & 0x3FFFFFFF; } - #endif /* HAVE_COMPRESS */ + longlong Item_func_length::val_int() { String *res=args[0]->val_str(&value); @@ -1078,6 +1113,7 @@ longlong Item_func_length::val_int() return (longlong) res->length(); } + longlong Item_func_char_length::val_int() { String *res=args[0]->val_str(&value); @@ -1090,6 +1126,7 @@ longlong Item_func_char_length::val_int() return (longlong) res->numchars(); } + longlong Item_func_coercibility::val_int() { if (args[0]->null_value) @@ -1101,12 +1138,14 @@ longlong Item_func_coercibility::val_int() return (longlong) args[0]->derivation(); } + void Item_func_locate::fix_length_and_dec() { maybe_null=0; max_length=11; agg_arg_collations_for_comparison(cmp_collation, args, 2); } + longlong Item_func_locate::val_int() { String *a=args[0]->val_str(&value1); @@ -1207,6 +1246,7 @@ longlong Item_func_field::val_int() return 0; } + void Item_func_field::fix_length_and_dec() { maybe_null=0; max_length=3; |