summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/typelib.h3
-rw-r--r--mysql-test/r/sp.result16
-rw-r--r--mysql-test/t/sp.test24
-rw-r--r--mysys/typelib.c51
-rw-r--r--sql/field.cc10
-rw-r--r--sql/field.h1
6 files changed, 105 insertions, 0 deletions
diff --git a/include/typelib.h b/include/typelib.h
index 4d6a90ad51e..fe19f1001d4 100644
--- a/include/typelib.h
+++ b/include/typelib.h
@@ -18,6 +18,8 @@
#ifndef _typelib_h
#define _typelib_h
+#include "my_alloc.h"
+
typedef struct st_typelib { /* Different types saved here */
unsigned int count; /* How many types */
const char *name; /* Name of typelib */
@@ -28,6 +30,7 @@ typedef struct st_typelib { /* Different types saved here */
extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
extern void make_type(char *to,unsigned int nr,TYPELIB *typelib);
extern const char *get_type(TYPELIB *typelib,unsigned int nr);
+extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from);
extern TYPELIB sql_protocol_typelib;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 6859de2ed63..fb2e456833c 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -5816,4 +5816,20 @@ DROP TABLE bug23760, bug23760_log|
DROP PROCEDURE bug23760_update_log|
DROP PROCEDURE bug23760_test_row_count|
DROP FUNCTION bug23760_rc_test|
+DROP PROCEDURE IF EXISTS bug24117|
+DROP TABLE IF EXISTS t3|
+CREATE TABLE t3(c1 ENUM('abc'))|
+INSERT INTO t3 VALUES('abc')|
+CREATE PROCEDURE bug24117()
+BEGIN
+DECLARE t3c1 ENUM('abc');
+DECLARE mycursor CURSOR FOR SELECT c1 FROM t3;
+OPEN mycursor;
+FLUSH TABLES;
+FETCH mycursor INTO t3c1;
+CLOSE mycursor;
+END|
+CALL bug24117()|
+DROP PROCEDURE bug24117|
+DROP TABLE t3|
drop table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index ba1180ffaff..19c70b1bd1e 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -6779,6 +6779,30 @@ DROP PROCEDURE bug23760_test_row_count|
DROP FUNCTION bug23760_rc_test|
#
+# BUG#24117: server crash on a FETCH with a cursor on a table which is not in
+# the table cache
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS bug24117|
+DROP TABLE IF EXISTS t3|
+--enable_warnings
+CREATE TABLE t3(c1 ENUM('abc'))|
+INSERT INTO t3 VALUES('abc')|
+CREATE PROCEDURE bug24117()
+BEGIN
+ DECLARE t3c1 ENUM('abc');
+ DECLARE mycursor CURSOR FOR SELECT c1 FROM t3;
+ OPEN mycursor;
+ FLUSH TABLES;
+ FETCH mycursor INTO t3c1;
+ CLOSE mycursor;
+END|
+CALL bug24117()|
+DROP PROCEDURE bug24117|
+DROP TABLE t3|
+
+#
# NOTE: The delimiter is `|`, and not `;`. It is changed to `;`
# at the end of the file!
#
diff --git a/mysys/typelib.c b/mysys/typelib.c
index d329b687668..8906b702aa8 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -119,3 +119,54 @@ const char *get_type(TYPELIB *typelib, uint nr)
return(typelib->type_names[nr]);
return "?";
}
+
+
+/*
+ Create a copy of a specified TYPELIB structure.
+
+ SYNOPSIS
+ copy_typelib()
+ root pointer to a MEM_ROOT object for allocations
+ from pointer to a source TYPELIB structure
+
+ RETURN
+ pointer to the new TYPELIB structure on successful copy, or
+ NULL otherwise
+*/
+
+TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from)
+{
+ TYPELIB *to;
+ uint i;
+
+ if (!from)
+ return NULL;
+
+ if (!(to= (TYPELIB*) alloc_root(root, sizeof(TYPELIB))))
+ return NULL;
+
+ if (!(to->type_names= (const char **)
+ alloc_root(root, (sizeof(char *) + sizeof(int)) * (from->count + 1))))
+ return NULL;
+ to->type_lengths= (unsigned int *)(to->type_names + from->count + 1);
+ to->count= from->count;
+ if (from->name)
+ {
+ if (!(to->name= strdup_root(root, from->name)))
+ return NULL;
+ }
+ else
+ to->name= NULL;
+
+ for (i= 0; i < from->count; i++)
+ {
+ if (!(to->type_names[i]= strmake_root(root, from->type_names[i],
+ from->type_lengths[i])))
+ return NULL;
+ to->type_lengths[i]= from->type_lengths[i];
+ }
+ to->type_names[to->count]= NULL;
+ to->type_lengths[to->count]= 0;
+
+ return to;
+}
diff --git a/sql/field.cc b/sql/field.cc
index 4245d401f53..0dd3dd6b417 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8029,6 +8029,16 @@ void Field_enum::sql_type(String &res) const
}
+Field *Field_enum::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type)
+{
+ Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
+ if (res)
+ res->typelib= copy_typelib(root, typelib);
+ return res;
+}
+
+
/*
set type.
This is a string which can have a collection of different values.
diff --git a/sql/field.h b/sql/field.h
index 3e2be248627..9d979e81c9c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1354,6 +1354,7 @@ public:
{
flags|=ENUM_FLAG;
}
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
enum_field_types type() const { return FIELD_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum Item_result cast_to_int_type () const { return INT_RESULT; }