diff options
-rw-r--r-- | mysql-test/r/gis.result | 18 | ||||
-rw-r--r-- | mysql-test/t/gis.test | 13 | ||||
-rw-r--r-- | sql/item.cc | 41 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/sql_type.cc | 98 | ||||
-rw-r--r-- | sql/sql_type.h | 33 |
6 files changed, 169 insertions, 40 deletions
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 1a4a4bb48fd..df773a15ec2 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -4300,5 +4300,23 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP PROCEDURE p1; # +# MDEV-12798 Item_param does not preserve exact field type in EXECUTE IMMEDIATE 'CREATE TABLE AS SELECT ?' USING POINT(1,1) +# +EXECUTE IMMEDIATE 'CREATE TABLE t1 AS SELECT ?' USING POINT(1,1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `?` point NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 AS SELECT ?'; +EXECUTE stmt USING POINT(1,1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `?` point NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# # End of 10.3 tests # diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 34797337b1d..ab9c792d523 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -2294,5 +2294,18 @@ CALL p1('geometrycollection'); DROP PROCEDURE p1; --echo # +--echo # MDEV-12798 Item_param does not preserve exact field type in EXECUTE IMMEDIATE 'CREATE TABLE AS SELECT ?' USING POINT(1,1) +--echo # +EXECUTE IMMEDIATE 'CREATE TABLE t1 AS SELECT ?' USING POINT(1,1); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 AS SELECT ?'; +EXECUTE stmt USING POINT(1,1); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo # --echo # End of 10.3 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 20945027dbc..e5ea5537acc 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3767,45 +3767,8 @@ bool Item_param::set_from_item(THD *thd, Item *item) struct st_value tmp; if (!item->save_in_value(&tmp)) { - unsigned_flag= item->unsigned_flag; - switch (item->cmp_type()) { - case REAL_RESULT: - set_double(tmp.value.m_double); - set_handler(&type_handler_double); - break; - case INT_RESULT: - set_int(tmp.value.m_longlong, MY_INT64_NUM_DECIMAL_DIGITS); - set_handler(&type_handler_longlong); - break; - case STRING_RESULT: - { - value.cs_info.set(thd, item->collation.collation); - /* - Exact value of max_length is not known unless data is converted to - charset of connection, so we have to set it later. - */ - set_handler(&type_handler_varchar); - - if (set_str(tmp.m_string.ptr(), tmp.m_string.length())) - DBUG_RETURN(1); - break; - } - case DECIMAL_RESULT: - { - set_decimal(&tmp.m_decimal, unsigned_flag); - set_handler(&type_handler_newdecimal); - break; - } - case TIME_RESULT: - { - set_time(&tmp.value.m_time, item->max_length, item->decimals); - set_handler(item->type_handler()); - break; - } - case ROW_RESULT: - DBUG_ASSERT(0); - set_null(); - } + if (item->type_handler()->Item_param_set_from_value(thd, this, item, &tmp)) + DBUG_RETURN(true); } else set_null(); diff --git a/sql/item.h b/sql/item.h index 4ef23755f94..0ff7deb479f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2943,7 +2943,8 @@ public: class Item_param :public Item_basic_value, private Settable_routine_parameter, public Rewritable_query_parameter, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Type_geometry_attributes { /* NO_VALUE is a special value meaning that the parameter has not been @@ -3075,6 +3076,9 @@ public: const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } + Field::geometry_type get_geometry_type() const + { return Type_geometry_attributes::get_geometry_type(); }; + Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index f632b47680c..d17f9f5927e 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -4180,6 +4180,104 @@ bool Type_handler_time_common:: /***************************************************************************/ +bool Type_handler_row:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + DBUG_ASSERT(0); + param->set_null(); + return true; +} + + +bool Type_handler_real_result:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= attr->unsigned_flag; + param->set_double(val->value.m_double); + param->set_handler(&type_handler_double); + return false; +} + + +bool Type_handler_int_result:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= attr->unsigned_flag; + param->set_int(val->value.m_longlong, MY_INT64_NUM_DECIMAL_DIGITS); + param->set_handler(&type_handler_longlong); + return false; +} + + +bool Type_handler_decimal_result:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= attr->unsigned_flag; + param->set_decimal(&val->m_decimal, attr->unsigned_flag); + param->set_handler(&type_handler_newdecimal); + return false; +} + + +bool Type_handler_string_result:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= false; + param->value.cs_info.set(thd, attr->collation.collation); + /* + Exact value of max_length is not known unless data is converted to + charset of connection, so we have to set it later. + */ + param->set_handler(&type_handler_varchar); + return param->set_str(val->m_string.ptr(), val->m_string.length()); +} + + +bool Type_handler_temporal_result:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= attr->unsigned_flag; + param->set_time(&val->value.m_time, attr->max_length, attr->decimals); + param->set_handler(this); + return false; +} + + +#ifdef HAVE_SPATIAL +bool Type_handler_geometry:: + Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *val) const +{ + param->unsigned_flag= false; + param->value.cs_info.set(thd, &my_charset_bin); + param->set_handler(&type_handler_geometry); + param->set_geometry_type(attr->uint_geometry_type()); + return param->set_str(val->m_string.ptr(), val->m_string.length()); +} +#endif + +/***************************************************************************/ + bool Type_handler_null:: Item_send(Item *item, Protocol *protocol, st_value *buf) const { diff --git a/sql/sql_type.h b/sql/sql_type.h index 8abc8e61510..5c134e7ba25 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -28,6 +28,7 @@ class Field; class Item; +class Item_param; class Item_cache; class Item_func_or_sum; class Item_sum_hybrid; @@ -698,6 +699,10 @@ public: virtual uint32 max_display_length(const Item *item) const= 0; virtual bool Item_save_in_value(Item *item, st_value *value) const= 0; + virtual bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const= 0; virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0; virtual int Item_save_in_field(Item *item, Field *field, bool no_conversions) const= 0; @@ -942,6 +947,10 @@ public: return DECIMAL_MAX_PRECISION; } bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { DBUG_ASSERT(0); @@ -1164,6 +1173,10 @@ public: SORT_FIELD_ATTR *attr) const; uint Item_decimal_precision(const Item *item) const; bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -1226,6 +1239,10 @@ public: uint32 max_display_length(const Item *item) const; uint Item_decimal_precision(const Item *item) const; bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { return Item_send_str(item, protocol, buf); @@ -1288,6 +1305,10 @@ public: SORT_FIELD_ATTR *attr) const; uint Item_decimal_precision(const Item *item) const; bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -1343,6 +1364,10 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; uint32 max_display_length(const Item *item) const; bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, @@ -1419,6 +1444,10 @@ public: } uint Item_decimal_precision(const Item *item) const; bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { return Item_send_str(item, protocol, buf); @@ -2182,6 +2211,10 @@ public: { return false; // Materialization does not work with GEOMETRY columns } + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; Field *make_table_field(const LEX_CSTRING *name, |