mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Getting closer to be more SQL99 in dyadic operations
mysql-test/r/ctype_collate.result: NO COLLATION has less coercibility than IMPLICIT and COERCIBLE sql/item.cc: Function to choose collation for dyadic operations sql/item.h: NO COLLATION has less coercibility than IMPLICIT and COERCIBLE sql/item_func.cc: Function to choose collation for dyadic operations sql/item_strfunc.cc: Function to choose collation for dyadic operations sql/item_strfunc.h: Use arg's attributes
This commit is contained in:
parent
926a11940e
commit
80630f12f3
6 changed files with 66 additions and 49 deletions
|
@ -523,7 +523,7 @@ Variable_name Value
|
|||
client_collation latin1
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1 2 1
|
||||
latin1 latin1 3 1
|
||||
SET NAMES latin1 COLLATE latin1_bin;
|
||||
SHOW VARIABLES LIKE 'client_collation';
|
||||
Variable_name Value
|
||||
|
@ -538,35 +538,35 @@ Variable_name Value
|
|||
client_collation latin1_bin
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1_bin 2 0
|
||||
latin1 latin1_bin 3 0
|
||||
SET NAMES koi8r;
|
||||
SHOW VARIABLES LIKE 'client_collation';
|
||||
Variable_name Value
|
||||
client_collation koi8r
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1 2 1
|
||||
latin1 latin1 3 1
|
||||
SET COLLATION koi8r_bin;
|
||||
SHOW VARIABLES LIKE 'client_collation';
|
||||
Variable_name Value
|
||||
client_collation koi8r_bin
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1 2 1
|
||||
latin1 latin1 3 1
|
||||
SET COLLATION DEFAULT;
|
||||
SHOW VARIABLES LIKE 'client_collation';
|
||||
Variable_name Value
|
||||
client_collation koi8r
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1 2 1
|
||||
latin1 latin1 3 1
|
||||
SET NAMES DEFAULT;
|
||||
SHOW VARIABLES LIKE 'client_collation';
|
||||
Variable_name Value
|
||||
client_collation latin1
|
||||
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
|
||||
charset('a') collation('a') coercibility('a') 'a'='A'
|
||||
latin1 latin1 2 1
|
||||
latin1 latin1 3 1
|
||||
SET NAMES latin1 COLLATE koi8r;
|
||||
COLLATION 'koi8r' is not valid for CHARACTER SET 'latin1'
|
||||
SET NAMES 'DEFAULT';
|
||||
|
|
36
sql/item.cc
36
sql/item.cc
|
@ -172,6 +172,39 @@ CHARSET_INFO * Item::default_charset() const
|
|||
return current_thd->db_charset;
|
||||
}
|
||||
|
||||
bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1,
|
||||
CHARSET_INFO *cs2, enum coercion co2)
|
||||
{
|
||||
if (cs1 == &my_charset_bin || cs2 == &my_charset_bin)
|
||||
{
|
||||
set_charset(&my_charset_bin, COER_NOCOLL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!my_charset_same(cs1,cs2))
|
||||
{
|
||||
set_charset(&my_charset_bin, COER_NOCOLL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (co1 < co2)
|
||||
{
|
||||
set_charset(cs1, co1);
|
||||
}
|
||||
else if (co2 < co1)
|
||||
{
|
||||
set_charset(cs2, co2);
|
||||
}
|
||||
else // co2 == co1
|
||||
{
|
||||
if (cs1 != cs2)
|
||||
set_charset(&my_charset_bin, COER_NOCOLL);
|
||||
else
|
||||
set_charset(cs2, co2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
|
||||
{
|
||||
set_field(f);
|
||||
|
@ -195,8 +228,7 @@ void Item_field::set_field(Field *field_par)
|
|||
table_name=field_par->table_name;
|
||||
field_name=field_par->field_name;
|
||||
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
|
||||
set_charset(field_par->charset());
|
||||
coercibility= COER_IMPLICIT;
|
||||
set_charset(field_par->charset(), COER_IMPLICIT);
|
||||
}
|
||||
|
||||
const char *Item_ident::full_name() const
|
||||
|
|
11
sql/item.h
11
sql/item.h
|
@ -39,8 +39,8 @@ public:
|
|||
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
|
||||
|
||||
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
|
||||
enum coercion { COER_NOCOLL=3, COER_COERCIBLE=2,
|
||||
COER_IMPLICIT=1, COER_EXPLICIT=0 };
|
||||
enum coercion { COER_COERCIBLE=3, COER_IMPLICIT=2,
|
||||
COER_NOCOLL=1, COER_EXPLICIT=0 };
|
||||
|
||||
String str_value; /* used to store value */
|
||||
my_string name; /* Name from select */
|
||||
|
@ -113,6 +113,13 @@ public:
|
|||
CHARSET_INFO *default_charset() const;
|
||||
CHARSET_INFO *charset() const { return str_value.charset(); };
|
||||
void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
|
||||
void set_charset(CHARSET_INFO *cs, enum coercion coer)
|
||||
{
|
||||
str_value.set_charset(cs);
|
||||
coercibility= coer;
|
||||
}
|
||||
bool set_charset(CHARSET_INFO *cs1, enum coercion co1,
|
||||
CHARSET_INFO *cs2, enum coercion co2);
|
||||
virtual void set_outer_resolving() {}
|
||||
|
||||
// Row emulation
|
||||
|
|
|
@ -107,7 +107,6 @@ 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
|
||||
bool first_coll= 1;
|
||||
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
|
||||
{
|
||||
if ((*arg)->fix_fields(thd, tables, arg) ||
|
||||
|
@ -116,38 +115,6 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
if ((*arg)->maybe_null)
|
||||
maybe_null=1;
|
||||
|
||||
if ((*arg)->result_type() == STRING_RESULT)
|
||||
{
|
||||
/*
|
||||
Set return character set to first argument if we are returning a
|
||||
string.
|
||||
*/
|
||||
if (first_coll)
|
||||
{
|
||||
set_charset((*arg)->charset());
|
||||
coercibility= (*args)->coercibility;
|
||||
first_coll= 0;
|
||||
}
|
||||
else if ((*arg)->charset() == &my_charset_bin ||
|
||||
charset() == &my_charset_bin)
|
||||
{
|
||||
set_charset(&my_charset_bin);
|
||||
coercibility= COER_NOCOLL;
|
||||
}
|
||||
else if ((*arg)->coercibility < coercibility)
|
||||
{
|
||||
if (!my_charset_same(charset(),(*arg)->charset()))
|
||||
{
|
||||
set_charset(&my_charset_bin);
|
||||
coercibility= COER_NOCOLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
coercibility= (*arg)->coercibility;
|
||||
set_charset((*arg)->charset());
|
||||
}
|
||||
}
|
||||
}
|
||||
with_sum_func= with_sum_func || (*arg)->with_sum_func;
|
||||
used_tables_cache|=(*arg)->used_tables();
|
||||
const_item_cache&= (*arg)->const_item();
|
||||
|
|
|
@ -321,9 +321,17 @@ null:
|
|||
|
||||
void Item_func_concat::fix_length_and_dec()
|
||||
{
|
||||
bool first_coll= 1;
|
||||
max_length=0;
|
||||
|
||||
set_charset(args[0]->charset(),args[0]->coercibility);
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
max_length+=args[i]->max_length;
|
||||
set_charset(charset(), coercibility,
|
||||
args[i]->charset(), args[i]->coercibility);
|
||||
}
|
||||
|
||||
if (max_length > MAX_BLOB_WIDTH)
|
||||
{
|
||||
max_length=MAX_BLOB_WIDTH;
|
||||
|
@ -978,6 +986,7 @@ void Item_func_substr::fix_length_and_dec()
|
|||
{
|
||||
max_length=args[0]->max_length;
|
||||
|
||||
set_charset(args[0]->charset(), args[0]->coercibility);
|
||||
if (args[1]->const_item())
|
||||
{
|
||||
int32 start=(int32) args[1]->val_int()-1;
|
||||
|
@ -1791,6 +1800,7 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value,
|
|||
|
||||
void Item_func_repeat::fix_length_and_dec()
|
||||
{
|
||||
set_charset(args[0]->charset(), args[0]->coercibility);
|
||||
if (args[1]->const_item())
|
||||
{
|
||||
max_length=(long) (args[0]->max_length * args[1]->val_int());
|
||||
|
@ -2028,8 +2038,7 @@ String *Item_func_conv_charset::val_str(String *str)
|
|||
void Item_func_conv_charset::fix_length_and_dec()
|
||||
{
|
||||
max_length = args[0]->max_length*conv_charset->mbmaxlen;
|
||||
coercibility= COER_IMPLICIT;
|
||||
set_charset(conv_charset);
|
||||
set_charset(conv_charset, COER_IMPLICIT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2171,9 +2180,7 @@ bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables,
|
|||
set_collation->name,args[0]->charset()->csname);
|
||||
return 1;
|
||||
}
|
||||
set_charset(set_collation);
|
||||
|
||||
coercibility= COER_EXPLICIT;
|
||||
set_charset(set_collation, COER_EXPLICIT);
|
||||
with_sum_func= with_sum_func || args[0]->with_sum_func;
|
||||
used_tables_cache=args[0]->used_tables();
|
||||
const_item_cache=args[0]->const_item();
|
||||
|
|
|
@ -151,7 +151,11 @@ class Item_str_conv :public Item_str_func
|
|||
{
|
||||
public:
|
||||
Item_str_conv(Item *item) :Item_str_func(item) {}
|
||||
void fix_length_and_dec() { max_length = args[0]->max_length; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
set_charset(args[0]->charset(), args[0]->coercibility);
|
||||
max_length = args[0]->max_length;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue