Commit 597f3dfa authored by unknown's avatar unknown

Merge


sql/mysql_priv.h:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
parents da43c3cc 62556b00
...@@ -2967,4 +2967,47 @@ begin end; ...@@ -2967,4 +2967,47 @@ begin end;
goto label1; goto label1;
end| end|
drop procedure bug6898| drop procedure bug6898|
drop function if exists bug9102|
create function bug9102() returns blob return 'a'|
select bug9102()|
bug9102()
a
drop function bug9102|
drop function if exists bug7648|
create function bug7648() returns bit(8) return 'a'|
select bug7648()|
bug7648()
a
drop function bug7648|
drop function if exists bug9775|
create function bug9775(v1 char(1)) returns enum('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('c')|
bug9775('a') bug9775('b') bug9775('c')
a b
drop function bug9775|
create function bug9775(v1 int) returns enum('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3)|
bug9775(1) bug9775(2) bug9775(3)
a b
drop function bug9775|
create function bug9775(v1 char(1)) returns set('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')|
bug9775('a') bug9775('b') bug9775('a,b') bug9775('c')
a b a,b
drop function bug9775|
create function bug9775(v1 int) returns set('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3),bug9775(4)|
bug9775(1) bug9775(2) bug9775(3) bug9775(4)
a b a,b
drop function bug9775|
drop function if exists bug8861|
create function bug8861(v1 int) returns year return v1|
select bug8861(05)|
bug8861(05)
2005
set @x = bug8861(05)|
select @x|
@x
2005
drop function bug8861|
drop table t1,t2; drop table t1,t2;
...@@ -3644,6 +3644,62 @@ end| ...@@ -3644,6 +3644,62 @@ end|
drop procedure bug6898| drop procedure bug6898|
#
# BUG#9102: Stored proccedures: function which returns blob causes crash
#
--disable_warnings
drop function if exists bug9102|
--enable_warnings
create function bug9102() returns blob return 'a'|
select bug9102()|
drop function bug9102|
#
# BUG#7648: Stored procedure crash when invoking a function that returns a bit
#
--disable_warnings
drop function if exists bug7648|
--enable_warnings
create function bug7648() returns bit(8) return 'a'|
select bug7648()|
drop function bug7648|
#
# BUG#9775: crash if create function that returns enum or set
#
--disable_warnings
drop function if exists bug9775|
--enable_warnings
create function bug9775(v1 char(1)) returns enum('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('c')|
drop function bug9775|
create function bug9775(v1 int) returns enum('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3)|
drop function bug9775|
create function bug9775(v1 char(1)) returns set('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')|
drop function bug9775|
create function bug9775(v1 int) returns set('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3),bug9775(4)|
drop function bug9775|
#
# BUG#8861: If Return is a YEAR data type, value is not shown in year format
#
--disable_warnings
drop function if exists bug8861|
--enable_warnings
create function bug8861(v1 int) returns year return v1|
select bug8861(05)|
set @x = bug8861(05)|
select @x|
drop function bug8861|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -4461,7 +4461,7 @@ longlong Item_func_row_count::val_int() ...@@ -4461,7 +4461,7 @@ longlong Item_func_row_count::val_int()
Item_func_sp::Item_func_sp(sp_name *name) Item_func_sp::Item_func_sp(sp_name *name)
:Item_func(), m_name(name), m_sp(NULL) :Item_func(), m_name(name), m_sp(NULL), result_field(NULL)
{ {
maybe_null= 1; maybe_null= 1;
m_name->init_qname(current_thd); m_name->init_qname(current_thd);
...@@ -4470,7 +4470,7 @@ Item_func_sp::Item_func_sp(sp_name *name) ...@@ -4470,7 +4470,7 @@ Item_func_sp::Item_func_sp(sp_name *name)
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list) Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
:Item_func(list), m_name(name), m_sp(NULL) :Item_func(list), m_name(name), m_sp(NULL), result_field(NULL)
{ {
maybe_null= 1; maybe_null= 1;
m_name->init_qname(current_thd); m_name->init_qname(current_thd);
...@@ -4526,6 +4526,29 @@ Item_func_sp::sp_result_field(void) const ...@@ -4526,6 +4526,29 @@ Item_func_sp::sp_result_field(void) const
} }
int
Item_func_sp::execute(Field **flp)
{
Item *it;
Field *f;
if (execute(&it))
{
null_value= 1;
return 1;
}
if (!(f= *flp))
{
*flp= f= sp_result_field();
f->move_field((f->pack_length() > sizeof(result_buf)) ?
sql_alloc(f->pack_length()) : result_buf);
f->null_ptr= (uchar *)&null_value;
f->null_bit= 1;
}
it->save_in_field(f, 1);
return f->is_null();
}
int int
Item_func_sp::execute(Item **itp) Item_func_sp::execute(Item **itp)
{ {
...@@ -4601,6 +4624,8 @@ Item_func_sp::field_type() const ...@@ -4601,6 +4624,8 @@ Item_func_sp::field_type() const
Field *field= 0; Field *field= 0;
DBUG_ENTER("Item_func_sp::field_type"); DBUG_ENTER("Item_func_sp::field_type");
if (result_field)
DBUG_RETURN(result_field->type());
if (! m_sp) if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field())) if ((field= sp_result_field()))
...@@ -4621,6 +4646,8 @@ Item_func_sp::result_type() const ...@@ -4621,6 +4646,8 @@ Item_func_sp::result_type() const
DBUG_ENTER("Item_func_sp::result_type"); DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp)); DBUG_PRINT("info", ("m_sp = %p", m_sp));
if (result_field)
DBUG_RETURN(result_field->result_type());
if (! m_sp) if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field())) if ((field= sp_result_field()))
...@@ -4636,8 +4663,16 @@ Item_func_sp::result_type() const ...@@ -4636,8 +4663,16 @@ Item_func_sp::result_type() const
void void
Item_func_sp::fix_length_and_dec() Item_func_sp::fix_length_and_dec()
{ {
Field *field= result_field;
DBUG_ENTER("Item_func_sp::fix_length_and_dec"); DBUG_ENTER("Item_func_sp::fix_length_and_dec");
if (result_field)
{
decimals= result_field->decimals();
max_length= result_field->representation_length();
DBUG_VOID_RETURN;
}
if (! m_sp) if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if (! m_sp) if (! m_sp)
...@@ -4646,29 +4681,28 @@ Item_func_sp::fix_length_and_dec() ...@@ -4646,29 +4681,28 @@ Item_func_sp::fix_length_and_dec()
} }
else else
{ {
switch (result_type()) { if (!field)
field= sp_result_field();
decimals= field->decimals();
max_length= field->representation_length();
switch (field->result_type()) {
case STRING_RESULT: case STRING_RESULT:
maybe_null= 1; maybe_null= 1;
max_length= MAX_BLOB_WIDTH;
break;
case REAL_RESULT: case REAL_RESULT:
decimals= NOT_FIXED_DEC;
max_length= float_length(decimals);
break;
case INT_RESULT: case INT_RESULT:
decimals= 0;
max_length= 21;
break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
// TODO: where to find real precision and scale? break;
decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
max_length= DECIMAL_MAX_LENGTH;
case ROW_RESULT: case ROW_RESULT:
default: default:
// This case should never be chosen // This case should never be chosen
DBUG_ASSERT(0); DBUG_ASSERT(0);
break; break;
} }
if (field != result_field)
delete field;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -1283,8 +1283,11 @@ class Item_func_sp :public Item_func ...@@ -1283,8 +1283,11 @@ class Item_func_sp :public Item_func
sp_name *m_name; sp_name *m_name;
mutable sp_head *m_sp; mutable sp_head *m_sp;
TABLE *dummy_table; TABLE *dummy_table;
Field *result_field;
char result_buf[64];
int execute(Item **itp); int execute(Item **itp);
int execute(Field **flp);
Field *sp_result_field(void) const; Field *sp_result_field(void) const;
public: public:
...@@ -1296,6 +1299,12 @@ class Item_func_sp :public Item_func ...@@ -1296,6 +1299,12 @@ class Item_func_sp :public Item_func
virtual ~Item_func_sp() virtual ~Item_func_sp()
{} {}
void cleanup()
{
Item_func::cleanup();
result_field= NULL;
}
const char *func_name() const; const char *func_name() const;
enum enum_field_types field_type() const; enum enum_field_types field_type() const;
...@@ -1308,53 +1317,30 @@ class Item_func_sp :public Item_func ...@@ -1308,53 +1317,30 @@ class Item_func_sp :public Item_func
longlong val_int() longlong val_int()
{ {
return (longlong)Item_func_sp::val_real(); if (execute(&result_field))
return 0LL;
return result_field->val_int();
} }
double val_real() double val_real()
{ {
Item *it; if (execute(&result_field))
double d;
if (execute(&it))
{
null_value= 1;
return 0.0; return 0.0;
} return result_field->val_real();
d= it->val_real();
null_value= it->null_value;
return d;
} }
my_decimal *val_decimal(my_decimal *dec_buf) my_decimal *val_decimal(my_decimal *dec_buf)
{ {
Item *it; if (execute(&result_field))
my_decimal *result;
if (execute(&it))
{
null_value= 1;
return NULL; return NULL;
} return result_field->val_decimal(dec_buf);
result= it->val_decimal(dec_buf);
null_value= it->null_value;
return result;
} }
String *val_str(String *str) String *val_str(String *str)
{ {
Item *it; if (execute(&result_field))
String *s;
if (execute(&it))
{
null_value= 1;
return NULL; return NULL;
} return result_field->val_str(str);
s= it->val_str(str);
null_value= it->null_value;
return s;
} }
void fix_length_and_dec(); void fix_length_and_dec();
......
...@@ -647,6 +647,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -647,6 +647,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
bool group, bool modify_item, bool group, bool modify_item,
uint convert_blob_length); uint convert_blob_length);
void sp_prepare_create_field(THD *thd, create_field *sql_field);
int prepare_create_field(create_field *sql_field, int prepare_create_field(create_field *sql_field,
uint *blob_columns, uint *blob_columns,
int *timestamps, int *timestamps_with_niladic, int *timestamps, int *timestamps_with_niladic,
......
...@@ -774,6 +774,7 @@ bool Protocol_simple::store(const char *from, uint length, ...@@ -774,6 +774,7 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF #ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 || DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL || field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_BIT || field_types[field_pos] == MYSQL_TYPE_BIT ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL || field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM && (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
......
...@@ -370,6 +370,7 @@ TYPELIB * ...@@ -370,6 +370,7 @@ TYPELIB *
sp_head::create_typelib(List<String> *src) sp_head::create_typelib(List<String> *src)
{ {
TYPELIB *result= NULL; TYPELIB *result= NULL;
CHARSET_INFO *cs= m_returns_cs;
DBUG_ENTER("sp_head::clone_typelib"); DBUG_ENTER("sp_head::clone_typelib");
if (src->elements) if (src->elements)
{ {
...@@ -377,12 +378,39 @@ sp_head::create_typelib(List<String> *src) ...@@ -377,12 +378,39 @@ sp_head::create_typelib(List<String> *src)
result->count= src->elements; result->count= src->elements;
result->name= ""; result->name= "";
if (!(result->type_names=(const char **) if (!(result->type_names=(const char **)
alloc_root(mem_root,sizeof(char *)*(result->count+1)))) alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1))))
return 0; return 0;
result->type_lengths= (unsigned int *)(result->type_names + result->count+1);
List_iterator<String> it(*src); List_iterator<String> it(*src);
String conv, *tmp;
uint32 dummy;
for (uint i=0; i<result->count; i++) for (uint i=0; i<result->count; i++)
result->type_names[i]= strdup_root(mem_root, (it++)->c_ptr()); {
tmp = it++;
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
char *buf= (char*) alloc_root(mem_root,conv.length()+1);
memcpy(buf, conv.ptr(), conv.length());
buf[conv.length()]= '\0';
result->type_names[i]= buf;
result->type_lengths[i]= conv.length();
}
else {
result->type_names[i]= strdup_root(mem_root, tmp->c_ptr());
result->type_lengths[i]= tmp->length();
}
// Strip trailing spaces.
uint lengthsp= cs->cset->lengthsp(cs, result->type_names[i],
result->type_lengths[i]);
result->type_lengths[i]= lengthsp;
((uchar *)result->type_names[i])[lengthsp]= '\0';
}
result->type_names[result->count]= 0; result->type_names[result->count]= 0;
result->type_lengths[result->count]= 0;
} }
return result; return result;
} }
......
...@@ -1351,6 +1351,77 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1351,6 +1351,77 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
} }
/*
Preparation of create_field for SP function return values.
Based on code used in the inner loop of mysql_prepare_table() above
SYNOPSIS
sp_prepare_create_field()
thd Thread object
sql_field Field to prepare
DESCRIPTION
Prepares the field structures for field creation.
*/
void sp_prepare_create_field(THD *thd, create_field *sql_field)
{
if (sql_field->sql_type == FIELD_TYPE_SET ||
sql_field->sql_type == FIELD_TYPE_ENUM)
{
uint32 field_length, dummy;
if (sql_field->sql_type == FIELD_TYPE_SET)
{
calculate_interval_lengths(sql_field->charset,
sql_field->interval, &dummy,
&field_length);
sql_field->length= field_length +
(sql_field->interval->count - 1);
}
else /* FIELD_TYPE_ENUM */
{
calculate_interval_lengths(sql_field->charset,
sql_field->interval,
&field_length, &dummy);
sql_field->length= field_length;
}
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
}
if (sql_field->sql_type == FIELD_TYPE_BIT)
{
sql_field->pack_flag= FIELDFLAG_NUMBER |
FIELDFLAG_TREAT_BIT_AS_CHAR;
}
sql_field->create_length_to_internal_length();
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
!(sql_field->flags & BLOB_FLAG))
{
/* Convert long VARCHAR columns to TEXT or BLOB */
char warn_buff[MYSQL_ERRMSG_SIZE];
sql_field->sql_type= FIELD_TYPE_BLOB;
sql_field->flags|= BLOB_FLAG;
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
"VARCHAR",
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
warn_buff);
}
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
{
if (sql_field->sql_type == FIELD_TYPE_BLOB)
{
/* The user has given a length to the blob column */
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
}
sql_field->length= 0; // Probably from an item
}
}
/* /*
Create a table Create a table
......
...@@ -1407,6 +1407,16 @@ create_function_tail: ...@@ -1407,6 +1407,16 @@ create_function_tail:
lex->uint_geom_type))) lex->uint_geom_type)))
YYABORT; YYABORT;
sp->m_returns_cs= new_field->charset;
if (new_field->sql_type == FIELD_TYPE_SET ||
new_field->sql_type == FIELD_TYPE_ENUM)
{
new_field->interval=
sp->create_typelib(&new_field->interval_list);
}
sp_prepare_create_field(YYTHD, new_field);
if (prepare_create_field(new_field, &unused1, &unused2, &unused2, if (prepare_create_field(new_field, &unused1, &unused2, &unused2,
0)) 0))
YYABORT; YYABORT;
...@@ -1415,8 +1425,8 @@ create_function_tail: ...@@ -1415,8 +1425,8 @@ create_function_tail:
sp->m_returns_cs= new_field->charset; sp->m_returns_cs= new_field->charset;
sp->m_returns_len= new_field->length; sp->m_returns_len= new_field->length;
sp->m_returns_pack= new_field->pack_flag; sp->m_returns_pack= new_field->pack_flag;
sp->m_returns_typelib= sp->m_returns_typelib= new_field->interval;
sp->create_typelib(&new_field->interval_list); new_field->interval= NULL;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment