Commit 6e308347 authored by unknown's avatar unknown

Bug#28763: Selecting geometry fields in UNION caused server crash.

This bug was introduced by the fix for the bug#27300. In this fix a section
of code was added to the Item::tmp_table_field_from_field_type method.
This section intended to create Field_geom fields for the Item_geometry_func
class and its descendants. In order to get the geometry type of the current
item it casted "this" to the Item_geometry_func* type. But the
Item::tmp_table_field_from_field_type method is also used for creation of
fields for UNION and in this case this method is called for an object of the
Item_type_holder class and the cast to the Item_geometry_func* type causes 
a server crash.

Now the Item::tmp_table_field_from_field_type method correctly works when it's
called for both the Item_type_holder and the Item_geometry_func classes.
The new geometry_type variable is added to the Item_type_holder class.
The new method called get_geometry_type is added to the Item_field
and the Field classes. It returns geometry type from the field for the
Item_field and the Field_geom classes and fails an assert for other Field
descendants.


sql/field.h:
  Bug#28763: Selecting geometry fields in UNION caused server crash.
  The new method called get_geometry_type is added to the Field class.
  It returns geometry type of the field for the Field_geom class
  and fails an assert for other Field descendants.
sql/item.cc:
  Bug#28763: Selecting geometry fields in UNION caused server crash.
  Now the Item::tmp_table_field_from_field_type method correctly works when it's
  called for both the Item_type_holder and the Item_geometry_func classes.
mysql-test/r/gis.result:
  Added a test case for the bug#28763: Selecting geometry fields in UNION caused server crash.
mysql-test/t/gis.test:
  Added a test case for the bug#28763: Selecting geometry fields in UNION caused server crash.
sql/item.h:
  Bug#28763: Selecting geometry fields in UNION caused server crash.
  The new method called get_geometry_type is added to the Item_field class.
  It returns geometry type from the field.
  The new geometry_type variable is added to the Item_type_holder class.
parent eeab724f
...@@ -864,4 +864,25 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL; ...@@ -864,4 +864,25 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL;
Overlaps(@horiz1, @point2) Overlaps(@horiz1, @point2)
0 0
DROP TABLE t1; DROP TABLE t1;
create table t1(f1 geometry, f2 point, f3 linestring);
select f1 from t1 union select f1 from t1;
f1
insert into t1 (f2,f3) values (GeomFromText('POINT(1 1)'),
GeomFromText('LINESTRING(0 0,1 1,2 2)'));
select AsText(f2),AsText(f3) from t1;
AsText(f2) AsText(f3)
POINT(1 1) LINESTRING(0 0,1 1,2 2)
select AsText(a) from (select f2 as a from t1 union select f3 from t1) t;
AsText(a)
POINT(1 1)
LINESTRING(0 0,1 1,2 2)
create table t2 as select f2 as a from t1 union select f3 from t1;
desc t2;
Field Type Null Key Default Extra
a point YES NULL
select AsText(a) from t2;
AsText(a)
POINT(1 1)
LINESTRING(0 0,1 1,2 2)
drop table t1, t2;
End of 5.0 tests End of 5.0 tests
...@@ -557,4 +557,17 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL; ...@@ -557,4 +557,17 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#28763: Selecting geometry fields in UNION caused server crash.
#
create table t1(f1 geometry, f2 point, f3 linestring);
select f1 from t1 union select f1 from t1;
insert into t1 (f2,f3) values (GeomFromText('POINT(1 1)'),
GeomFromText('LINESTRING(0 0,1 1,2 2)'));
select AsText(f2),AsText(f3) from t1;
select AsText(a) from (select f2 as a from t1 union select f3 from t1) t;
create table t2 as select f2 as a from t1 union select f3 from t1;
desc t2;
select AsText(a) from t2;
drop table t1, t2;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -360,7 +360,11 @@ class Field ...@@ -360,7 +360,11 @@ class Field
{ {
return field_length / charset()->mbmaxlen; return field_length / charset()->mbmaxlen;
} }
virtual geometry_type get_geometry_type()
{
/* shouldn't get here. */
DBUG_ASSERT(0);
}
friend bool reopen_table(THD *,struct st_table *,bool); friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options, friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value); ulonglong auto_increment_value);
...@@ -1325,6 +1329,7 @@ class Field_geom :public Field_blob { ...@@ -1325,6 +1329,7 @@ class Field_geom :public Field_blob {
uint get_key_image(char *buff,uint length,imagetype type); uint get_key_image(char *buff,uint length,imagetype type);
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
int reset(void) { return !maybe_null() || Field_blob::reset(); } int reset(void) { return !maybe_null() || Field_blob::reset(); }
geometry_type get_geometry_type() { return geom_type; };
}; };
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
......
...@@ -4317,7 +4317,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) ...@@ -4317,7 +4317,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_GEOMETRY:
return new Field_geom(max_length, maybe_null, name, table, return new Field_geom(max_length, maybe_null, name, table,
(Field::geometry_type) (Field::geometry_type)
((Item_geometry_func *)this)->get_geometry_type()); ((type() == Item::TYPE_HOLDER) ?
((Item_type_holder *)this)->get_geometry_type() :
((Item_geometry_func *)this)->get_geometry_type()));
} }
} }
...@@ -6422,6 +6424,10 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) ...@@ -6422,6 +6424,10 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
if (Field::result_merge_type(fld_type) == INT_RESULT) if (Field::result_merge_type(fld_type) == INT_RESULT)
decimals= 0; decimals= 0;
prev_decimal_int_part= item->decimal_int_part(); prev_decimal_int_part= item->decimal_int_part();
if (item->field_type() == MYSQL_TYPE_GEOMETRY)
geometry_type= (item->type() == Item::FIELD_ITEM) ?
((Item_field *)item)->get_geometry_type() :
(Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type();
} }
......
...@@ -1304,6 +1304,11 @@ class Item_field :public Item_ident ...@@ -1304,6 +1304,11 @@ class Item_field :public Item_ident
int fix_outer_field(THD *thd, Field **field, Item **reference); int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(byte *select_arg); virtual Item *update_value_transformer(byte *select_arg);
void print(String *str); void print(String *str);
Field::geometry_type get_geometry_type()
{
DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY);
return field->get_geometry_type();
}
friend class Item_default_value; friend class Item_default_value;
friend class Item_insert_value; friend class Item_insert_value;
friend class st_select_lex_unit; friend class st_select_lex_unit;
...@@ -2563,6 +2568,7 @@ class Item_type_holder: public Item ...@@ -2563,6 +2568,7 @@ class Item_type_holder: public Item
protected: protected:
TYPELIB *enum_set_typelib; TYPELIB *enum_set_typelib;
enum_field_types fld_type; enum_field_types fld_type;
Field::geometry_type geometry_type;
void get_full_info(Item *item); void get_full_info(Item *item);
...@@ -2582,6 +2588,7 @@ class Item_type_holder: public Item ...@@ -2582,6 +2588,7 @@ class Item_type_holder: public Item
Field *make_field_by_type(TABLE *table); Field *make_field_by_type(TABLE *table);
static uint32 display_length(Item *item); static uint32 display_length(Item *item);
static enum_field_types get_real_type(Item *); static enum_field_types get_real_type(Item *);
Field::geometry_type get_geometry_type() { return geometry_type; };
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment