item.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:90k
- /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #ifdef USE_PRAGMA_IMPLEMENTATION
- #pragma implementation // gcc: Class implementation
- #endif
- #include "mysql_priv.h"
- #include <m_ctype.h>
- #include "my_dir.h"
- static void mark_as_dependent(THD *thd,
- SELECT_LEX *last, SELECT_LEX *current,
- Item_ident *item);
- const String my_null_string("NULL", 4, default_charset_info);
- /*****************************************************************************
- ** Item functions
- *****************************************************************************/
- /* Init all special items */
- void item_init(void)
- {
- item_user_lock_init();
- }
- Item::Item():
- fixed(0)
- {
- marker= 0;
- maybe_null=null_value=with_sum_func=unsigned_flag=0;
- collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
- name= 0;
- decimals= 0; max_length= 0;
- /* Put item in free list so that we can free all items at end */
- THD *thd= current_thd;
- next= thd->free_list;
- thd->free_list= this;
- /*
- Item constructor can be called during execution other then SQL_COM
- command => we should check thd->lex->current_select on zero (thd->lex
- can be uninitialised)
- */
- if (thd->lex->current_select)
- {
- enum_parsing_place place=
- thd->lex->current_select->parsing_place;
- if (place == SELECT_LIST ||
- place == IN_HAVING)
- thd->lex->current_select->select_n_having_items++;
- }
- }
- /*
- Constructor used by Item_field, Item_*_ref & agregate (sum) functions.
- Used for duplicating lists in processing queries with temporary
- tables
- */
- Item::Item(THD *thd, Item *item):
- str_value(item->str_value),
- name(item->name),
- max_length(item->max_length),
- marker(item->marker),
- decimals(item->decimals),
- maybe_null(item->maybe_null),
- null_value(item->null_value),
- unsigned_flag(item->unsigned_flag),
- with_sum_func(item->with_sum_func),
- fixed(item->fixed),
- collation(item->collation)
- {
- next= thd->free_list; // Put in free list
- thd->free_list= this;
- }
- void Item::print_item_w_name(String *str)
- {
- print(str);
- if (name)
- {
- str->append(" AS `", 5);
- str->append(name);
- str->append('`');
- }
- }
- Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par)
- :orig_db_name(db_name_par), orig_table_name(table_name_par),
- orig_field_name(field_name_par),
- db_name(db_name_par), table_name(table_name_par),
- field_name(field_name_par), cached_field_index(NO_CACHED_FIELD_INDEX),
- cached_table(0), depended_from(0)
- {
- name = (char*) field_name_par;
- }
- // Constructor used by Item_field & Item_*_ref (see Item comment)
- Item_ident::Item_ident(THD *thd, Item_ident *item)
- :Item(thd, item),
- orig_db_name(item->orig_db_name),
- orig_table_name(item->orig_table_name),
- orig_field_name(item->orig_field_name),
- db_name(item->db_name),
- table_name(item->table_name),
- field_name(item->field_name),
- cached_field_index(item->cached_field_index),
- cached_table(item->cached_table),
- depended_from(item->depended_from)
- {}
- void Item_ident::cleanup()
- {
- DBUG_ENTER("Item_ident::cleanup");
- DBUG_PRINT("enter", ("b:%s(%s), t:%s(%s), f:%s(%s)",
- db_name, orig_db_name,
- table_name, orig_table_name,
- field_name, orig_field_name));
- Item::cleanup();
- db_name= orig_db_name;
- table_name= orig_table_name;
- field_name= orig_field_name;
- DBUG_VOID_RETURN;
- }
- bool Item_ident::remove_dependence_processor(byte * arg)
- {
- DBUG_ENTER("Item_ident::remove_dependence_processor");
- if (depended_from == (st_select_lex *) arg)
- depended_from= 0;
- DBUG_RETURN(0);
- }
- bool Item::check_cols(uint c)
- {
- if (c != 1)
- {
- my_error(ER_OPERAND_COLUMNS, MYF(0), c);
- return 1;
- }
- return 0;
- }
- void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
- {
- if (!length)
- {
- /* Empty string, used by AS or internal function like last_insert_id() */
- name= (char*) str;
- return;
- }
- if (cs->ctype)
- {
- // This will probably need a better implementation in the future:
- // a function in CHARSET_INFO structure.
- while (length && !my_isgraph(cs,*str))
- { // Fix problem with yacc
- length--;
- str++;
- }
- }
- if (!my_charset_same(cs, system_charset_info))
- {
- uint32 res_length;
- name= sql_strmake_with_convert(str, length, cs,
- MAX_ALIAS_NAME, system_charset_info,
- &res_length);
- }
- else
- name=sql_strmake(str, min(length,MAX_ALIAS_NAME));
- }
- /*
- 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
- {
- /*
- Note, that this is never TRUE if item is a Item_param:
- for all basic constants we have special checks, and Item_param's
- type() can be only among basic constant types.
- */
- return type() == item->type() && name && item->name &&
- !my_strcasecmp(system_charset_info,name,item->name);
- }
- Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
- {
- Item_func_conv_charset *conv= new Item_func_conv_charset(this, tocs, 1);
- return conv->safe ? conv : NULL;
- }
- /*
- Created mostly for mysql_prepare_table(). Important
- when a string ENUM/SET column is described with a numeric default value:
- CREATE TABLE t1(a SET('a') DEFAULT 1);
- We cannot use generic Item::safe_charset_converter(), because
- the latter returns a non-fixed Item, so val_str() crashes afterwards.
- Override Item_num method, to return a fixed item.
- */
- Item *Item_num::safe_charset_converter(CHARSET_INFO *tocs)
- {
- Item_string *conv;
- char buf[64];
- String *s, tmp(buf, sizeof(buf), &my_charset_bin);
- s= val_str(&tmp);
- if ((conv= new Item_string(s->ptr(), s->length(), s->charset())))
- {
- conv->str_value.copy();
- conv->str_value.shrink_to_length();
- }
- return conv;
- }
- Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
- {
- Item_string *conv;
- uint conv_errors;
- String tmp, cstr, *ostr= val_str(&tmp);
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
- if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
- {
- /*
- Safe conversion is not possible (or EOM).
- We could not convert a string into the requested character set
- without data loss. The target charset does not cover all the
- characters from the string. Operation cannot be done correctly.
- */
- return NULL;
- }
- conv->str_value.copy();
- /*
- The above line executes str_value.realloc() internally,
- which alligns Alloced_length using ALLIGN_SIZE.
- In the case of Item_string::str_value we don't want
- Alloced_length to be longer than str_length.
- Otherwise, some functions like Item_func_concat::val_str()
- try to reuse str_value as a buffer for concatenation result
- for optimization purposes, so our string constant become
- corrupted. See bug#8785 for more details.
- Let's shrink Alloced_length to str_length to avoid this problem.
- */
- conv->str_value.shrink_to_length();
- return conv;
- }
- Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
- {
- if (const_item())
- {
- Item_string *conv;
- uint conv_errors;
- char buf[MAX_FIELD_WIDTH];
- String tmp(buf, sizeof(buf), &my_charset_bin);
- String cstr, *ostr= val_str(&tmp);
- /*
- As safe_charset_converter is not executed for
- a parameter bound to NULL, ostr should never be 0.
- */
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
- if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
- return NULL;
- conv->str_value.copy();
- conv->str_value.shrink_to_length();
- return conv;
- }
- return NULL;
- }
- bool Item_string::eq(const Item *item, bool binary_cmp) const
- {
- if (type() == item->type() && item->basic_const_item())
- {
- if (binary_cmp)
- return !stringcmp(&str_value, &item->str_value);
- return !sortcmp(&str_value, &item->str_value, collation.collation);
- }
- return 0;
- }
- /*
- Get the value of the function as a TIME structure.
- As a extra convenience the time structure is reset on error!
- */
- bool Item::get_date(TIME *ltime,uint fuzzydate)
- {
- char buff[40];
- String tmp(buff,sizeof(buff), &my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_datetime_with_warn(res->ptr(), res->length(),
- ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
- {
- bzero((char*) ltime,sizeof(*ltime));
- return 1;
- }
- return 0;
- }
- /*
- Get time of first argument.
- As a extra convenience the time structure is reset on error!
- */
- bool Item::get_time(TIME *ltime)
- {
- char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_time_with_warn(res->ptr(), res->length(), ltime))
- {
- bzero((char*) ltime,sizeof(*ltime));
- return 1;
- }
- return 0;
- }
- CHARSET_INFO *Item::default_charset()
- {
- return current_thd->variables.collation_connection;
- }
- /*
- Move SUM items out from item tree and replace with reference
- SYNOPSIS
- split_sum_func2()
- thd Thread handler
- ref_pointer_array Pointer to array of reference fields
- fields All fields in select
- ref Pointer to item
- NOTES
- This is from split_sum_func2() for items that should be split
- All found SUM items are added FIRST in the fields list and
- we replace the item with a reference.
- thd->fatal_error() may be called if we are out of memory
- */
- void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
- List<Item> &fields, Item **ref)
- {
- if (type() != SUM_FUNC_ITEM && with_sum_func)
- {
- /* Will split complicated items and ignore simple ones */
- split_sum_func(thd, ref_pointer_array, fields);
- }
- else if ((type() == SUM_FUNC_ITEM ||
- (used_tables() & ~PARAM_TABLE_BIT)) &&
- type() != REF_ITEM)
- {
- /*
- Replace item with a reference so that we can easily calculate
- it (in case of sum functions) or copy it (in case of fields)
- The test above is to ensure we don't do a reference for things
- that are constants (PARAM_TABLE_BIT is in effect a constant)
- or already referenced (for example an item in HAVING)
- */
- uint el= fields.elements;
- Item *new_item;
- ref_pointer_array[el]= this;
- if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
- return; // fatal_error is set
- fields.push_front(this);
- ref_pointer_array[el]= this;
- thd->change_item_tree(ref, new_item);
- }
- }
- /*
- Aggregate two collations together taking
- into account their coercibility (aka derivation):
- 0 == DERIVATION_EXPLICIT - an explicitely written COLLATE clause
- 1 == DERIVATION_NONE - a mix of two different collations
- 2 == DERIVATION_IMPLICIT - a column
- 3 == DERIVATION_COERCIBLE - a string constant
- The most important rules are:
- 1. If collations are the same:
- chose this collation, and the strongest derivation.
- 2. If collations are different:
- - Character sets may differ, but only if conversion without
- data loss is possible. The caller provides flags whether
- character set conversion attempts should be done. If no
- flags are substituted, then the character sets must be the same.
- Currently processed flags are:
- MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
- MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
- - two EXPLICIT collations produce an error, e.g. this is wrong:
- CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci)
- - the side with smaller derivation value wins,
- i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column.
- - if derivations are the same, we have DERIVATION_NONE,
- we'll wait for an explicit COLLATE clause which possibly can
- come from another argument later: for example, this is valid,
- but we don't know yet when collecting the first two arguments:
- CONCAT(latin1_swedish_ci_column,
- latin1_german1_ci_column,
- expr COLLATE latin1_german2_ci)
- */
- bool DTCollation::aggregate(DTCollation &dt, uint flags)
- {
- if (!my_charset_same(collation, dt.collation))
- {
- /*
- We do allow to use binary strings (like BLOBS)
- together with character strings.
- Binaries have more precedance than a character
- string of the same derivation.
- */
- if (collation == &my_charset_bin)
- {
- if (derivation <= dt.derivation)
- ; // Do nothing
- else
- {
- set(dt);
- }
- }
- else if (dt.collation == &my_charset_bin)
- {
- if (dt.derivation <= derivation)
- {
- set(dt);
- }
- else
- ; // Do nothing
- }
- else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
- collation->state & MY_CS_UNICODE &&
- (derivation < dt.derivation ||
- (derivation == dt.derivation &&
- !(dt.collation->state & MY_CS_UNICODE))))
- {
- // Do nothing
- }
- else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
- dt.collation->state & MY_CS_UNICODE &&
- (dt.derivation < derivation ||
- (dt.derivation == derivation &&
- !(collation->state & MY_CS_UNICODE))))
- {
- set(dt);
- }
- else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
- derivation < dt.derivation &&
- dt.derivation >= DERIVATION_SYSCONST)
- {
- // Do nothing;
- }
- else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
- dt.derivation < derivation &&
- derivation >= DERIVATION_SYSCONST)
- {
- set(dt);
- }
- else
- {
- // Cannot apply conversion
- set(0, DERIVATION_NONE);
- return 1;
- }
- }
- else if (derivation < dt.derivation)
- {
- // Do nothing
- }
- else if (dt.derivation < derivation)
- {
- set(dt);
- }
- else
- {
- if (collation == dt.collation)
- {
- // Do nothing
- }
- else
- {
- if (derivation == DERIVATION_EXPLICIT)
- {
- set(0, DERIVATION_NONE);
- return 1;
- }
- if (collation->state & MY_CS_BINSORT)
- {
- return 0;
- }
- else if (dt.collation->state & MY_CS_BINSORT)
- {
- set(dt);
- return 0;
- }
- CHARSET_INFO *bin= get_charset_by_csname(collation->csname,
- MY_CS_BINSORT,MYF(0));
- set(bin, DERIVATION_NONE);
- }
- }
- return 0;
- }
- /******************************/
- 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(),
- c2.collation->name,c2.derivation_name(),
- fname);
- }
- static
- void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3,
- const char *fname)
- {
- my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- c3.collation->name,c3.derivation_name(),
- fname);
- }
- static
- void my_coll_agg_error(Item** args, uint count, const char *fname)
- {
- if (count == 2)
- my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
- else if (count == 3)
- my_coll_agg_error(args[0]->collation, args[1]->collation,
- args[2]->collation, fname);
- else
- my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
- }
- bool agg_item_collations(DTCollation &c, const char *fname,
- Item **av, uint count, uint flags)
- {
- uint i;
- c.set(av[0]->collation);
- for (i= 1; i < count; i++)
- {
- if (c.aggregate(av[i]->collation, flags))
- {
- my_coll_agg_error(av, count, fname);
- return TRUE;
- }
- }
- if ((flags & MY_COLL_DISALLOW_NONE) &&
- c.derivation == DERIVATION_NONE)
- {
- my_coll_agg_error(av, count, fname);
- return TRUE;
- }
- return FALSE;
- }
- bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
- Item **av, uint count, uint flags)
- {
- return (agg_item_collations(c, fname, av, count,
- flags | MY_COLL_DISALLOW_NONE));
- }
- /*
- Collect arguments' character sets together.
- We allow to apply automatic character set conversion in some cases.
- The conditions when conversion is possible are:
- - arguments A and B have different charsets
- - A wins according to coercibility rules
- (i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column)
- - character set of A is either superset for character set of B,
- or B is a string constant which can be converted into the
- character set of A without data loss.
-
- If all of the above is true, then it's possible to convert
- B into the character set of A, and then compare according
- to the collation of A.
-
- For functions with more than two arguments:
- collect(A,B,C) ::= collect(collect(A,B),C)
- */
- bool agg_item_charsets(DTCollation &coll, const char *fname,
- Item **args, uint nargs, uint flags)
- {
- Item **arg, **last, *safe_args[2];
- if (agg_item_collations(coll, fname, args, nargs, flags))
- return TRUE;
- /*
- For better error reporting: save the first and the second argument.
- We need this only if the the number of args is 3 or 2:
- - for a longer argument list, "Illegal mix of collations"
- doesn't display each argument's characteristics.
- - if nargs is 1, then this error cannot happen.
- */
- if (nargs >=2 && nargs <= 3)
- {
- safe_args[0]= args[0];
- safe_args[1]= args[1];
- }
- THD *thd= current_thd;
- Item_arena *arena, backup;
- bool res= FALSE;
- /*
- In case we're in statement prepare, create conversion item
- in its memory: it will be reused on each execute.
- */
- arena= thd->change_arena_if_needed(&backup);
- for (arg= args, last= args + nargs; arg < last; arg++)
- {
- Item* conv;
- uint32 dummy_offset;
- if (!String::needs_conversion(0, coll.collation,
- (*arg)->collation.collation,
- &dummy_offset))
- continue;
- if (!(conv= (*arg)->safe_charset_converter(coll.collation)))
- {
- if (nargs >=2 && nargs <= 3)
- {
- /* restore the original arguments for better error message */
- args[0]= safe_args[0];
- args[1]= safe_args[1];
- }
- my_coll_agg_error(args, nargs, fname);
- res= TRUE;
- break; // we cannot return here, we need to restore "arena".
- }
- conv->fix_fields(thd, 0, &conv);
- /*
- If in statement prepare, then we create a converter for two
- constant items, do it once and then reuse it.
- If we're in execution of a prepared statement, arena is NULL,
- and the conv was created in runtime memory. This can be
- the case only if the argument is a parameter marker ('?'),
- because for all true constants the charset converter has already
- been created in prepare. In this case register the change for
- rollback.
- */
- if (arena)
- *arg= conv;
- else
- thd->change_item_tree(arg, conv);
- }
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- return res;
- }
- /**********************************************/
- Item_field::Item_field(Field *f)
- :Item_ident(NullS, f->table_name, f->field_name)
- {
- set_field(f);
- /*
- field_name and talbe_name should not point to garbage
- if this item is to be reused
- */
- orig_table_name= orig_field_name= "";
- }
- Item_field::Item_field(THD *thd, Field *f)
- :Item_ident(f->table->table_cache_key, f->table_name, f->field_name)
- {
- /*
- We always need to provide Item_field with a fully qualified field
- name to avoid ambiguity when executing prepared statements like
- SELECT * from d1.t1, d2.t1; (assuming d1.t1 and d2.t1 have columns
- with same names).
- This is because prepared statements never deal with wildcards in
- select list ('*') and always fix fields using fully specified path
- (i.e. db.table.column).
- No check for OOM: if db_name is NULL, we'll just get
- "Field not found" error.
- We need to copy db_name, table_name and field_name because they must
- be allocated in the statement memory, not in table memory (the table
- structure can go away and pop up again between subsequent executions
- of a prepared statement).
- */
- if (thd->current_arena->is_stmt_prepare())
- {
- if (db_name)
- orig_db_name= thd->strdup(db_name);
- orig_table_name= thd->strdup(table_name);
- orig_field_name= thd->strdup(field_name);
- /*
- We don't restore 'name' in cleanup because it's not changed
- during execution. Still we need it to point to persistent
- memory if this item is to be reused.
- */
- name= (char*) orig_field_name;
- }
- set_field(f);
- }
- // Constructor need to process subselect with temporary tables (see Item)
- Item_field::Item_field(THD *thd, Item_field *item)
- :Item_ident(thd, item),
- field(item->field),
- result_field(item->result_field)
- {
- collation.set(DERIVATION_IMPLICIT);
- }
- void Item_field::set_field(Field *field_par)
- {
- field=result_field=field_par; // for easy coding with fields
- maybe_null=field->maybe_null();
- max_length=field_par->max_length();
- 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);
- collation.set(field_par->charset(), DERIVATION_IMPLICIT);
- fixed= 1;
- }
- /*
- Reset this item to point to a field from the new temporary table.
- This is used when we create a new temporary table for each execution
- of prepared statement.
- */
- void Item_field::reset_field(Field *f)
- {
- set_field(f);
- /* 'name' is pointing at field->field_name of old field */
- name= (char*) f->field_name;
- }
- const char *Item_ident::full_name() const
- {
- char *tmp;
- if (!table_name || !field_name)
- return field_name ? field_name : name ? name : "tmp_field";
- if (db_name && db_name[0])
- {
- tmp=(char*) sql_alloc((uint) strlen(db_name)+(uint) strlen(table_name)+
- (uint) strlen(field_name)+3);
- strxmov(tmp,db_name,".",table_name,".",field_name,NullS);
- }
- else
- {
- if (table_name[0])
- {
- tmp= (char*) sql_alloc((uint) strlen(table_name) +
- (uint) strlen(field_name) + 2);
- strxmov(tmp, table_name, ".", field_name, NullS);
- }
- else
- tmp= (char*) field_name;
- }
- return tmp;
- }
- /* ARGSUSED */
- String *Item_field::val_str(String *str)
- {
- DBUG_ASSERT(fixed == 1);
- if ((null_value=field->is_null()))
- return 0;
- str->set_charset(str_value.charset());
- return field->val_str(str,&str_value);
- }
- double Item_field::val()
- {
- DBUG_ASSERT(fixed == 1);
- if ((null_value=field->is_null()))
- return 0.0;
- return field->val_real();
- }
- longlong Item_field::val_int()
- {
- DBUG_ASSERT(fixed == 1);
- if ((null_value=field->is_null()))
- return 0;
- return field->val_int();
- }
- String *Item_field::str_result(String *str)
- {
- if ((null_value=result_field->is_null()))
- return 0;
- str->set_charset(str_value.charset());
- return result_field->val_str(str,&str_value);
- }
- bool Item_field::get_date(TIME *ltime,uint fuzzydate)
- {
- if ((null_value=field->is_null()) || field->get_date(ltime,fuzzydate))
- {
- bzero((char*) ltime,sizeof(*ltime));
- return 1;
- }
- return 0;
- }
- bool Item_field::get_date_result(TIME *ltime,uint fuzzydate)
- {
- if ((null_value=result_field->is_null()) ||
- result_field->get_date(ltime,fuzzydate))
- {
- bzero((char*) ltime,sizeof(*ltime));
- return 1;
- }
- return 0;
- }
- bool Item_field::get_time(TIME *ltime)
- {
- if ((null_value=field->is_null()) || field->get_time(ltime))
- {
- bzero((char*) ltime,sizeof(*ltime));
- return 1;
- }
- return 0;
- }
- double Item_field::val_result()
- {
- if ((null_value=result_field->is_null()))
- return 0.0;
- return result_field->val_real();
- }
- longlong Item_field::val_int_result()
- {
- if ((null_value=result_field->is_null()))
- return 0;
- return result_field->val_int();
- }
- bool Item_field::eq(const Item *item, bool binary_cmp) const
- {
- 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 && !strcmp(item_field->db_name,
- db_name))))));
- }
- table_map Item_field::used_tables() const
- {
- if (field->table->const_table)
- return 0; // const item
- return (depended_from ? OUTER_REF_TABLE_BIT : field->table->map);
- }
- Item *Item_field::get_tmp_table_item(THD *thd)
- {
- Item_field *new_item= new Item_field(thd, this);
- if (new_item)
- new_item->field= new_item->result_field;
- return new_item;
- }
- /*
- Create an item from a string we KNOW points to a valid longlong/ulonglong
- end