summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoracurtis@xiphis.org <>2005-04-20 18:08:42 +0100
committeracurtis@xiphis.org <>2005-04-20 18:08:42 +0100
commit8689083aca0c97457701551b776b1a9c9743c10d (patch)
tree07e3fe7c833631d8a9038ef91df990a4483c109a
parent77a9429c134ddf6eaf3936286280e216b2be03af (diff)
downloadmariadb-git-8689083aca0c97457701551b776b1a9c9743c10d.tar.gz
Bug#9775 - Stored procedures: crash if create function that returns enum or set
Fix bug and implement return type casting.
-rw-r--r--mysql-test/r/sp.result27
-rw-r--r--mysql-test/t/sp.test23
-rw-r--r--sql/item_func.cc62
-rw-r--r--sql/item_func.h58
-rw-r--r--sql/sp_head.cc8
5 files changed, 117 insertions, 61 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index a4a3968672f..5d93f252716 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -2960,14 +2960,35 @@ delete from t1|
drop function bug9902|
drop function if exists bug9102|
create function bug9102() returns blob return 'a'|
-select bug9102();
-drop function bug9102|
+select bug9102()|
bug9102()
a
-drop procedure if exists bug7648|
+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 table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 6c833b14482..9f76f7ec0e4 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -3643,7 +3643,7 @@ drop function bug9102|
# BUG#7648: Stored procedure crash when invoking a function that returns a bit
#
--disable_warnings
-drop procedure if exists bug7648|
+drop function if exists bug7648|
--enable_warnings
create function bug7648() returns bit(8) return 'a'|
select bug7648()|
@@ -3651,6 +3651,27 @@ 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#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c607efa0797..fb21551e22f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4461,7 +4461,7 @@ longlong Item_func_row_count::val_int()
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;
m_name->init_qname(current_thd);
@@ -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(list), m_name(name), m_sp(NULL)
+ :Item_func(list), m_name(name), m_sp(NULL), result_field(NULL)
{
maybe_null= 1;
m_name->init_qname(current_thd);
@@ -4527,6 +4527,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
Item_func_sp::execute(Item **itp)
{
DBUG_ENTER("Item_func_sp::execute");
@@ -4601,6 +4624,8 @@ Item_func_sp::field_type() const
Field *field= 0;
DBUG_ENTER("Item_func_sp::field_type");
+ if (result_field)
+ DBUG_RETURN(result_field->type());
if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
@@ -4621,6 +4646,8 @@ Item_func_sp::result_type() const
DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp));
+ if (result_field)
+ DBUG_RETURN(result_field->result_type());
if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
@@ -4636,8 +4663,16 @@ Item_func_sp::result_type() const
void
Item_func_sp::fix_length_and_dec()
{
+ Field *field= result_field;
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)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if (! m_sp)
@@ -4646,29 +4681,28 @@ Item_func_sp::fix_length_and_dec()
}
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:
maybe_null= 1;
- max_length= MAX_BLOB_WIDTH;
- break;
case REAL_RESULT:
- decimals= NOT_FIXED_DEC;
- max_length= float_length(decimals);
- break;
case INT_RESULT:
- decimals= 0;
- max_length= 21;
- break;
case DECIMAL_RESULT:
- // TODO: where to find real precision and scale?
- decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
- max_length= DECIMAL_MAX_LENGTH;
+ break;
case ROW_RESULT:
default:
// This case should never be chosen
DBUG_ASSERT(0);
break;
}
+
+ if (field != result_field)
+ delete field;
}
DBUG_VOID_RETURN;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index b39786e5544..ba5a6101e4c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1283,8 +1283,11 @@ private:
sp_name *m_name;
mutable sp_head *m_sp;
TABLE *dummy_table;
+ Field *result_field;
+ char result_buf[64];
int execute(Item **itp);
+ int execute(Field **flp);
Field *sp_result_field(void) const;
public:
@@ -1296,6 +1299,12 @@ public:
virtual ~Item_func_sp()
{}
+ void cleanup()
+ {
+ Item_func::cleanup();
+ result_field= NULL;
+ }
+
const char *func_name() const;
enum enum_field_types field_type() const;
@@ -1308,63 +1317,30 @@ public:
longlong val_int()
{
- Item *it;
- longlong l;
-
- if (execute(&it))
- {
- null_value= 1;
+ if (execute(&result_field))
return 0LL;
- }
- l= it->val_int();
- null_value= it->null_value;
- return l;
+ return result_field->val_int();
}
double val_real()
{
- Item *it;
- double d;
-
- if (execute(&it))
- {
- null_value= 1;
+ if (execute(&result_field))
return 0.0;
- }
- d= it->val_real();
- null_value= it->null_value;
- return d;
+ return result_field->val_real();
}
my_decimal *val_decimal(my_decimal *dec_buf)
{
- Item *it;
- my_decimal *result;
-
- if (execute(&it))
- {
- null_value= 1;
+ if (execute(&result_field))
return NULL;
- }
- result= it->val_decimal(dec_buf);
- null_value= it->null_value;
- return result;
+ return result_field->val_decimal(dec_buf);
}
-
String *val_str(String *str)
{
- Item *it;
- String *s;
-
- if (execute(&it))
- {
- null_value= 1;
+ if (execute(&result_field))
return NULL;
- }
- s= it->val_str(str);
- null_value= it->null_value;
- return s;
+ return result_field->val_str(str);
}
void fix_length_and_dec();
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index d1486cb234e..4ae76e4c6a5 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -378,8 +378,9 @@ sp_head::create_typelib(List<String> *src)
result->count= src->elements;
result->name= "";
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;
+ result->type_lengths= (unsigned int *)(result->type_names + result->count+1);
List_iterator<String> it(*src);
String conv, *tmp;
uint32 dummy;
@@ -397,8 +398,10 @@ sp_head::create_typelib(List<String> *src)
result->type_names[i]= buf;
result->type_lengths[i]= conv.length();
}
- else
+ 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],
@@ -407,6 +410,7 @@ sp_head::create_typelib(List<String> *src)
((uchar *)result->type_names[i])[lengthsp]= '\0';
}
result->type_names[result->count]= 0;
+ result->type_lengths[result->count]= 0;
}
return result;
}