diff options
-rw-r--r-- | sql/item.cc | 8 | ||||
-rw-r--r-- | sql/item.h | 12 | ||||
-rw-r--r-- | sql/item_create.cc | 5 | ||||
-rw-r--r-- | sql/item_create.h | 1 | ||||
-rw-r--r-- | sql/item_func.cc | 11 | ||||
-rw-r--r-- | sql/item_func.h | 9 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 |
8 files changed, 43 insertions, 6 deletions
diff --git a/sql/item.cc b/sql/item.cc index 50f87235196..ef2d68ab2bf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,6 +39,7 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; + coercibility=COER_NOCOLL; name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; @@ -63,7 +64,8 @@ Item::Item(THD *thd, Item &item): null_value(item.null_value), unsigned_flag(item.unsigned_flag), with_sum_func(item.with_sum_func), - fixed(item.fixed) + fixed(item.fixed), + coercibility(item.coercibility) { next=thd->free_list; // Put in free list thd->free_list= this; @@ -169,6 +171,7 @@ CHARSET_INFO * Item::thd_charset() const Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) { set_field(f); + coercibility= COER_IMPLICIT; fixed= 1; // This item is not needed in fix_fields } @@ -177,7 +180,7 @@ Item_field::Item_field(THD *thd, Item_field &item): Item_ident(thd, item), field(item.field), result_field(item.result_field) -{} +{ coercibility= COER_IMPLICIT; } void Item_field::set_field(Field *field_par) { @@ -189,6 +192,7 @@ void Item_field::set_field(Field *field_par) field_name=field_par->field_name; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); set_charset(field_par->charset()); + coercibility= COER_IMPLICIT; } const char *Item_ident::full_name() const diff --git a/sql/item.h b/sql/item.h index 531817c4844..ddf704ea1db 100644 --- a/sql/item.h +++ b/sql/item.h @@ -39,6 +39,8 @@ public: SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; + enum coercion { COER_NOCOLL=0, COER_COERCIBLE=1, + COER_IMPLICIT=2, COER_EXPLICIT=3 }; String str_value; /* used to store value */ my_string name; /* Name from select */ @@ -50,6 +52,7 @@ public: my_bool unsigned_flag; my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ + enum coercion coercibility; /* Precedence order of collation */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -155,7 +158,7 @@ public: Item_field(const char *db_par,const char *table_name_par, const char *field_name_par) :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) - {} + { coercibility= COER_IMPLICIT; } // Constructor need to process subselect with temporary tables (see Item) Item_field(THD *thd, Item_field &item); Item_field(Field *field); @@ -350,17 +353,20 @@ public: class Item_string :public Item { public: - Item_string(const char *str,uint length,CHARSET_INFO *cs) + Item_string(const char *str,uint length, + CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) { str_value.set(str,length,cs); + coercibility= coer; max_length=length; name=(char*) str_value.ptr(); decimals=NOT_FIXED_DEC; } Item_string(const char *name_par, const char *str, uint length, - CHARSET_INFO *cs) + CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) { str_value.set(str,length,cs); + coercibility= coer; max_length=length; name=(char*) name_par; decimals=NOT_FIXED_DEC; diff --git a/sql/item_create.cc b/sql/item_create.cc index 8b2cf52f660..d90c708fc0f 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -230,6 +230,11 @@ Item *create_func_bit_length(Item* a) return new Item_func_bit_length(a); } +Item *create_func_coercibility(Item* a) +{ + return new Item_func_coercibility(a); +} + Item *create_func_char_length(Item* a) { return new Item_func_char_length(a); diff --git a/sql/item_create.h b/sql/item_create.h index f7542a7b29f..135bd6b02c4 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -25,6 +25,7 @@ Item *create_func_asin(Item* a); Item *create_func_bin(Item* a); Item *create_func_bit_count(Item* a); Item *create_func_bit_length(Item* a); +Item *create_func_coercibility(Item* a); Item *create_func_ceiling(Item* a); Item *create_func_char_length(Item* a); Item *create_func_cast(Item *a, Item_cast cast_type); diff --git a/sql/item_func.cc b/sql/item_func.cc index c53cc5591dd..f228b04e0d0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -107,6 +107,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 0; // Fatal error if flag is set! if (arg_count) { // Print purify happy + coercibility= COER_NOCOLL; for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { if ((*arg)->fix_fields(thd, tables, arg) || @@ -1004,6 +1005,16 @@ longlong Item_func_char_length::val_int() return (longlong) (!args[0]->binary()) ? res->numchars() : res->length(); } +longlong Item_func_coercibility::val_int() +{ + if (args[0]->null_value) + { + null_value= 1; + return 0; + } + null_value= 0; + return (longlong) args[0]->coercibility; +} longlong Item_func_locate::val_int() { diff --git a/sql/item_func.h b/sql/item_func.h index 33bfc993b5f..b958b72d514 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -590,6 +590,15 @@ public: void fix_length_and_dec() { max_length=10; } }; +class Item_func_coercibility :public Item_int_func +{ +public: + Item_func_coercibility(Item *a) :Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "coercibility"; } + void fix_length_and_dec() { max_length=10; } +}; + class Item_func_locate :public Item_int_func { String value1,value2; diff --git a/sql/lex.h b/sql/lex.h index 95800fbd5af..de156af4ae2 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -441,6 +441,7 @@ static SYMBOL sql_functions[] = { { "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, { "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, { "COALESCE", SYM(COALESCE),0,0}, + { "COERCIBILITY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)}, { "CONCAT", SYM(CONCAT),0,0}, { "CONCAT_WS", SYM(CONCAT_WS),0,0}, { "CONNECTION_ID", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f4c625662b2..8e5fc819bf2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3778,7 +3778,7 @@ text_literal: { $$ = new Item_string($1.str,$1.length, YYTHD->variables.thd_charset); } | UNDERSCORE_CHARSET TEXT_STRING - { $$ = new Item_string($2.str,$2.length,Lex->charset); } + { $$ = new Item_string($2.str,$2.length,Lex->charset,Item::COER_EXPLICIT); } | text_literal TEXT_STRING { ((Item_string*) $1)->append($2.str,$2.length); }; |