summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
authorunknown <acurtis@xiphis.org>2005-04-20 18:08:42 +0100
committerunknown <acurtis@xiphis.org>2005-04-20 18:08:42 +0100
commitde8a3b31218f66948ecfc4ce4fee85a0285ae161 (patch)
tree07e3fe7c833631d8a9038ef91df990a4483c109a /sql/item_func.cc
parentf054047f022096efaeeec46381ddf86d59eed517 (diff)
downloadmariadb-git-de8a3b31218f66948ecfc4ce4fee85a0285ae161.tar.gz
Bug#9775 - Stored procedures: crash if create function that returns enum or set
Fix bug and implement return type casting. mysql-test/r/sp.result: Bug#9775 Test for bug + feature Fix previous tests mysql-test/t/sp.test: Bug#9775 Test for bug + feature Fix previous tests sql/item_func.cc: Bug#9775 new method Item_func_sp::execute(Field **) some optimizations. sql/item_func.h: Bug#9775 results for Item_func_sp pass through a Field of the return type. new method Item_func_sp::execute(Field **) sql/sp_head.cc: Bug#9775 missing initialiation for type_lengths in sp_head::create_typelib()
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc62
1 files changed, 48 insertions, 14 deletions
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;
}