summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-05-15 14:58:05 +0400
committerAlexander Barkov <bar@mariadb.org>2017-05-15 14:58:05 +0400
commit7c44b8afb781c533898dfb7321dd5cbb88c32ce0 (patch)
treea494865215069b226634bf69632caf0b09b3d84d
parent38acc29ccba3911318477baf6ddff79a9f8697a2 (diff)
downloadmariadb-git-7c44b8afb781c533898dfb7321dd5cbb88c32ce0.tar.gz
MDEV-12798 Item_param does not preserve exact field type in EXECUTE IMMEDIATE 'CREATE TABLE AS SELECT ?' USING POINT(1,1)
-rw-r--r--mysql-test/r/gis.result18
-rw-r--r--mysql-test/t/gis.test13
-rw-r--r--sql/item.cc41
-rw-r--r--sql/item.h6
-rw-r--r--sql/sql_type.cc98
-rw-r--r--sql/sql_type.h33
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,