diff options
author | bell@sanja.is.com.ua <> | 2003-06-25 23:52:15 +0300 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2003-06-25 23:52:15 +0300 |
commit | 7b77c5a2d3233290c7e307e8b78c48d28573b23e (patch) | |
tree | 445a886058facd2b39f84374786fced29406978c /sql/item.cc | |
parent | ac3fe4c81df253c4c736b9f238c4fcfa2ac0fd3b (diff) | |
parent | e009dce0c380d87430b03bdaef90374c1aa8e8eb (diff) | |
download | mariadb-git-7b77c5a2d3233290c7e307e8b78c48d28573b23e.tar.gz |
merged
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 117 |
1 files changed, 82 insertions, 35 deletions
diff --git a/sql/item.cc b/sql/item.cc index 4d48c0a90c8..804963b4c9a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,13 +39,15 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - coercibility=COER_IMPLICIT; + set_charset(&my_charset_bin, DERIVATION_COERCIBLE); name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; next= thd->free_list; // Put in free list thd->free_list= this; loop_id= 0; + if (thd->lex.current_select->parsing_place == SELECT_LEX_NODE::SELECT_LIST) + thd->lex.current_select->select_items++; } /* @@ -65,7 +67,7 @@ Item::Item(THD *thd, Item &item): unsigned_flag(item.unsigned_flag), with_sum_func(item.with_sum_func), fixed(item.fixed), - coercibility(item.coercibility) + collation(item.collation) { next=thd->free_list; // Put in free list thd->free_list= this; @@ -117,7 +119,9 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) /* - This function is only called when comparing items in the WHERE clause + This function is called when: + - Comparing items in the WHERE clause (when doing where optimization) + - When trying to find an ORDER BY/GROUP BY item in the SELECT part */ bool Item::eq(const Item *item, bool binary_cmp) const @@ -179,44 +183,61 @@ CHARSET_INFO * Item::default_charset() const return current_thd->variables.collation_connection; } -bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, - CHARSET_INFO *cs2, enum coercion co2) +bool DTCollation::aggregate(DTCollation &dt) { - if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) + if (collation == &my_charset_bin || dt.collation == &my_charset_bin) { - set_charset(&my_charset_bin, COER_NOCOLL); + collation= &my_charset_bin; + derivation= derivation > dt.derivation ? derivation : dt.derivation; return 0; } - - if (!my_charset_same(cs1,cs2)) - return 1; - - if (co1 < co2) + + if (!my_charset_same(collation, dt.collation)) { - set_charset(cs1, co1); + /* + We do allow to use binary strings (like BLOBS) + together with character strings. + Binaries have more precedance + */ + if ((derivation <= dt.derivation) && (collation == &my_charset_bin)) + { + // Do nothing + } + else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin)) + { + set(dt); + } + else + { + set(0, DERIVATION_NONE); + return 1; + } } - else if (co2 < co1) + else if (derivation < dt.derivation) { - set_charset(cs2, co2); + // Do nothing } - else // co2 == co1 + else if (dt.derivation < derivation) { - if (cs1 != cs2) + set(dt); + } + else + { + if (collation == dt.collation) { - if (co1 == COER_EXPLICIT) - { - return 1; - } - else + // Do nothing + } + else + { + if (derivation == DERIVATION_EXPLICIT) { - CHARSET_INFO *bin= get_charset_by_csname(cs1->csname, MY_CS_BINSORT,MYF(0)); - if (!bin) - return 1; - set_charset(bin, COER_NOCOLL); + set(0, DERIVATION_NONE); + return 1; } + CHARSET_INFO *bin= get_charset_by_csname(collation->csname, + MY_CS_BINSORT,MYF(0)); + set(bin, DERIVATION_NONE); } - else - set_charset(cs2, co2); } return 0; } @@ -224,7 +245,7 @@ bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) { set_field(f); - coercibility= COER_IMPLICIT; + set_charset(DERIVATION_IMPLICIT); fixed= 1; // This item is not needed in fix_fields } @@ -233,7 +254,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; } +{ set_charset(DERIVATION_IMPLICIT); } void Item_field::set_field(Field *field_par) { @@ -243,8 +264,9 @@ void Item_field::set_field(Field *field_par) decimals= field->decimals(); table_name=field_par->table_name; field_name=field_par->field_name; + db_name=field_par->table->table_cache_key; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); - set_charset(field_par->charset(), COER_IMPLICIT); + set_charset(field_par->charset(), DERIVATION_IMPLICIT); } const char *Item_ident::full_name() const @@ -344,9 +366,34 @@ longlong Item_field::val_int_result() return result_field->val_int(); } + bool Item_field::eq(const Item *item, bool binary_cmp) const { - return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field; + if (item->type() != FIELD_ITEM) + return 0; + + Item_field *item_field= (Item_field*) item; + if (item_field->field) + return item_field->field == field; + /* + We may come here when we are trying to find a function in a GROUP BY + clause from the select list. + In this case the '100 % correct' way to do this would be to first + run fix_fields() on the GROUP BY item and then retry this function, but + I think it's better to relax the checking a bit as we will in + most cases do the correct thing by just checking the field name. + (In cases where we would choose wrong we would have to generate a + ER_NON_UNIQ_ERROR). + */ + return (!my_strcasecmp(system_charset_info, item_field->name, + field_name) && + (!item_field->table_name || + (!my_strcasecmp(table_alias_charset, item_field->table_name, + table_name) && + (!item_field->db_name || + (item_field->db_name && !my_strcasecmp(table_alias_charset, + item_field->db_name, + db_name)))))); } table_map Item_field::used_tables() const @@ -837,7 +884,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return rf->fix_fields(thd, tables, ref) || rf->check_cols(1); } } - } + } else if (!tmp) return -1; @@ -1070,7 +1117,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length) str+=2; } *ptr=0; // Keep purify happy - coercibility= COER_COERCIBLE; + set_charset(&my_charset_bin, DERIVATION_COERCIBLE); } longlong Item_varbinary::val_int() @@ -1450,7 +1497,7 @@ bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, I Field *field=field_arg->field; /* charset doesn't matter here, it's to avoid sigsegv only */ set_field(new Field_null(0,0,Field::NONE,field->field_name,field->table, - default_charset_info)); + &my_charset_bin)); } return 0; } |