summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc157
1 files changed, 129 insertions, 28 deletions
diff --git a/sql/item.cc b/sql/item.cc
index fa75819605f..64d059caea7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -22,7 +22,6 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#include "my_dir.h"
-#include <assert.h>
/*****************************************************************************
** Item functions
@@ -47,6 +46,30 @@ Item::Item():
loop_id= 0;
}
+Item::Item(Item &item):
+ loop_id(0),
+ 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)
+{
+ next=current_thd->free_list; // Put in free list
+ current_thd->free_list= this;
+}
+
+Item_ident::Item_ident(Item_ident &item):
+ Item(item),
+ db_name(item.db_name),
+ table_name(item.table_name),
+ field_name(item.field_name),
+ depended_from(item.depended_from)
+{}
bool Item::check_loop(uint id)
{
@@ -116,7 +139,7 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const
bool Item::get_date(TIME *ltime,bool fuzzydate)
{
char buff[40];
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff), my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
{
@@ -134,7 +157,7 @@ bool Item::get_date(TIME *ltime,bool fuzzydate)
bool Item::get_time(TIME *ltime)
{
char buff[40];
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff),my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_time(res->ptr(),res->length(),ltime))
{
@@ -155,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
fixed= 1; // This item is not needed in fix_fields
}
+Item_field::Item_field(Item_field &item):
+ Item_ident(item),
+ field(item.field),
+ result_field(item.result_field)
+{}
void Item_field::set_field(Field *field_par)
{
@@ -193,6 +221,7 @@ String *Item_field::val_str(String *str)
{
if ((null_value=field->is_null()))
return 0;
+ str->set_charset(str_value.charset());
return field->val_str(str,&str_value);
}
@@ -215,6 +244,7 @@ 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);
}
@@ -264,6 +294,13 @@ table_map Item_field::used_tables() const
return (depended_from? RAND_TABLE_BIT : field->table->map);
}
+Item * Item_field::get_tmp_table_item()
+{
+ Item_field *new_item= new Item_field(*this);
+ if (new_item)
+ new_item->field= new_item->result_field;
+ return new_item;
+}
String *Item_int::val_str(String *str)
{
@@ -346,6 +383,25 @@ void Item_param::set_value(const char *str, uint length)
}
+void Item_param::set_time(TIME *tm, timestamp_type type)
+{
+ ltime.year= tm->year;
+ ltime.month= tm->month;
+ ltime.day= tm->day;
+
+ ltime.hour= tm->hour;
+ ltime.minute= tm->minute;
+ ltime.second= tm->second;
+
+ ltime.second_part= tm->second_part;
+
+ ltime.time_type= type;
+
+ item_is_time= true;
+ item_type= STRING_ITEM;
+}
+
+
void Item_param::set_longdata(const char *str, ulong length)
{
str_value.append(str,length);
@@ -368,17 +424,29 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
{
double nr=val();
return (field->store(nr)) ? -1 : 0;
+ }
+ if (item_is_time)
+ {
+ field->store_time(&ltime, ltime.time_type);
+ return 0;
}
String *result=val_str(&str_value);
return (field->store(result->ptr(),result->length(),field->charset())) ? -1 : 0;
}
+bool Item_param::get_time(TIME *res)
+{
+ *res=ltime;
+ return 0;
+}
double Item_param::val()
{
+ int err;
switch (item_result_type) {
case STRING_RESULT:
- return (double)my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)0);
+ return (double) my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), (char**) 0, &err);
case INT_RESULT:
return (double)int_value;
default:
@@ -389,9 +457,12 @@ double Item_param::val()
longlong Item_param::val_int()
{
+ int err;
switch (item_result_type) {
case STRING_RESULT:
- return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10);
+ return my_strntoll(str_value.charset(),
+ str_value.ptr(),str_value.length(),10,
+ (char**) 0,&err);
case REAL_RESULT:
return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5));
default:
@@ -502,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd,
struct st_table_list *tables,
Item ** reference)
{
- List_iterator<Item> li(list);
- Item *item;
- for (uint i= 0; (item= li++) && i < pos; i++);
- if (item)
- {
- ref= li.ref();
- return Item_ref_null_helper::fix_fields(thd, tables, reference);
- }
- else
+ if (select_lex->item_list.elements <= pos)
{
ref= 0;
my_error(ER_CARDINALITY_COL, MYF(0), pos);
return 1;
}
+ ref= select_lex->ref_pointer_array + pos;
+ return Item_ref_null_helper::fix_fields(thd, tables, reference);
}
double Item_ref_null_helper::val()
@@ -561,8 +626,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/
SELECT_LEX *last= 0;
-
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0;
+#endif
Item **refer= (Item **)not_found_item;
+ uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
@@ -574,7 +642,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(), &where,
0)) != not_found_field)
break;
- if ((refer= find_item_in_list(this, sl->item_list,
+ if ((refer= find_item_in_list(this, sl->item_list, &counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
@@ -594,12 +662,20 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
else if (refer != (Item **)not_found_item)
{
+ if (!(*refer)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+
Item_ref *r;
- *ref= r= new Item_ref(refer, (char *)table_name,
+ *ref= r= new Item_ref(last->ref_pointer_array + counter-1
+ , (char *)table_name,
(char *)field_name);
if (!r)
return 1;
- if (r->check_cols(1) || r->fix_fields(thd, tables, ref))
+ if (r->fix_fields(thd, tables, ref) || r->check_cols(1))
return 1;
r->depended_from= last;
cursel->mark_as_dependent(last);
@@ -623,7 +699,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!rf)
return 1;
(rf)->outer_resolving= outer_resolving;
- return rf->check_cols(1) || rf->fix_fields(thd, tables, ref);
+ return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
}
}
}
@@ -1008,6 +1084,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ uint counter= 0;
if (!ref)
{
TABLE_LIST *where= 0;
@@ -1022,6 +1099,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (outer_resolving ||
(ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
+ &counter,
((sl &&
thd->lex.current_select->master_unit()->
first_select()->linkage !=
@@ -1044,12 +1122,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select())
{
if ((ref= find_item_in_list(this, (last= sl)->item_list,
- REPORT_EXCEPT_NOT_FOUND)) !=
+ &counter,
+ REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
if ((tmp= find_field_in_tables(thd, this,
sl->get_table_list(), &where,
- 0)) != not_found_field);
+ 0)) != not_found_field)
+ break;
if (sl->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE)
break; // do not look over derived table
@@ -1064,6 +1144,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error
find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
+ &counter,
REPORT_ALL_ERRORS);
ref= 0;
return 1;
@@ -1080,17 +1161,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
}
else
{
- depended_from= last;
+ if (!(*ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+ ref= (depended_from= last)->ref_pointer_array + counter-1;
thd->lex.current_select->mark_as_dependent(last);
thd->add_possible_loop(this);
}
}
else if (!ref)
return 1;
+ else
+ {
+ if (!(*ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+ ref= thd->lex.current_select->ref_pointer_array + counter-1;
+ }
+
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
}
+
if (((*ref)->with_sum_func &&
(depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
@@ -1147,7 +1246,7 @@ Item *resolve_const_item(Item *item,Item *comp_item)
if (res_type == STRING_RESULT)
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),NULL),*result;
+ String tmp(buff,sizeof(buff),my_charset_bin),*result;
result=item->val_str(&tmp);
if (item->null_value)
{
@@ -1202,8 +1301,8 @@ bool field_is_equal_to_item(Field *field,Item *item)
{
char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH];
- String item_tmp(item_buff,sizeof(item_buff),NULL),*item_result;
- String field_tmp(field_buff,sizeof(field_buff),NULL);
+ String item_tmp(item_buff,sizeof(item_buff),my_charset_bin),*item_result;
+ String field_tmp(field_buff,sizeof(field_buff),my_charset_bin);
item_result=item->val_str(&item_tmp);
if (item->null_value)
return 1; // This must be true
@@ -1260,17 +1359,19 @@ void Item_cache_str::store(Item *item)
}
double Item_cache_str::val()
{
+ int err;
if (value)
- return my_strntod(value->charset(), value->ptr(),
- value->length(), (char**)0);
+ return my_strntod(value->charset(), (char*) value->ptr(),
+ value->length(), (char**) 0, &err);
else
return (double)0;
}
longlong Item_cache_str::val_int()
{
+ int err;
if (value)
return my_strntoll(value->charset(), value->ptr(),
- value->length(), (char**) 0, 10);
+ value->length(), 10, (char**) 0, &err);
else
return (longlong)0;
}