diff --git a/plugin/type_geom/plugin.cc b/plugin/type_geom/plugin.cc index 3e9f1fb5572..aa2f9255f17 100644 --- a/plugin/type_geom/plugin.cc +++ b/plugin/type_geom/plugin.cc @@ -21,6 +21,7 @@ #include #include "sql_show.h" // get_all_tables() #include "sql_error.h" // convert_error_to_warning() +#include "sql_type_geom.h" /*********** INFORMATION_SCHEMA.SPATIEL_REF_SYS *******************/ diff --git a/sql/field.cc b/sql/field.cc index 5a2d7920e20..10994ecd885 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8781,242 +8781,6 @@ longlong Field_blob_compressed::val_int(void) } -#ifdef HAVE_SPATIAL -/* Values 1-40 reserved for 1-byte options, - 41-80 for 2-byte options, - 81-120 for 4-byte options, - 121-160 for 8-byte options, - other - varied length in next 1-3 bytes. -*/ -enum extra2_gis_field_options { - FIELDGEOM_END=0, - FIELDGEOM_STORAGE_MODEL=1, - FIELDGEOM_PRECISION=2, - FIELDGEOM_SCALE=3, - FIELDGEOM_SRID=81, -}; - - -uint gis_field_options_image(uchar *buff, List &create_fields) -{ - uint image_size= 0; - List_iterator it(create_fields); - Create_field *field; - while ((field= it++)) - { - if (field->real_field_type() != MYSQL_TYPE_GEOMETRY) - continue; - if (buff) - { - uchar *cbuf= buff + image_size; - - cbuf[0]= FIELDGEOM_STORAGE_MODEL; - cbuf[1]= (uchar) Field_geom::GEOM_STORAGE_WKB; - - cbuf[2]= FIELDGEOM_PRECISION; - cbuf[3]= (uchar) field->length; - - cbuf[4]= FIELDGEOM_SCALE; - cbuf[5]= (uchar) field->decimals; - - cbuf[6]= FIELDGEOM_SRID; - int4store(cbuf + 7, ((uint32) field->srid)); - - cbuf[11]= FIELDGEOM_END; - } - image_size+= 12; - } - - return image_size; -} - - -uint gis_field_options_read(const uchar *buf, size_t buf_len, - Field_geom::storage_type *st_type,uint *precision, uint *scale, uint *srid) -{ - const uchar *buf_end= buf + buf_len; - const uchar *cbuf= buf; - int option_id; - - *precision= *scale= *srid= 0; - *st_type= Field_geom::GEOM_STORAGE_WKB; - - if (!buf) /* can only happen with the old FRM file */ - goto end_of_record; - - while (cbuf < buf_end) - { - switch ((option_id= *(cbuf++))) - { - case FIELDGEOM_STORAGE_MODEL: - *st_type= (Field_geom::storage_type) cbuf[0]; - break; - case FIELDGEOM_PRECISION: - *precision= cbuf[0]; - break; - case FIELDGEOM_SCALE: - *scale= cbuf[0]; - break; - case FIELDGEOM_SRID: - *srid= uint4korr(cbuf); - break; - case FIELDGEOM_END: - goto end_of_record; - } - if (option_id > 0 && option_id <= 40) - cbuf+= 1; - else if (option_id > 40 && option_id <= 80) - cbuf+= 2; - else if (option_id > 80 && option_id <= 120) - cbuf+= 4; - else if (option_id > 120 && option_id <= 160) - cbuf+= 8; - else /* > 160 and <=255 */ - cbuf+= cbuf[0] ? 1 + cbuf[0] : 3 + uint2korr(cbuf+1); - } - -end_of_record: - return (uint)(cbuf - buf); -} - - - -void Field_geom::sql_type(String &res) const -{ - CHARSET_INFO *cs= &my_charset_latin1; - const Name tmp= m_type_handler->name(); - res.set(tmp.ptr(), tmp.length(), cs); -} - - -int Field_geom::store(double nr) -{ - my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, - ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); - return -1; -} - - -int Field_geom::store(longlong nr, bool unsigned_val) -{ - my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, - ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); - return -1; -} - - -int Field_geom::store_decimal(const my_decimal *) -{ - my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, - ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); - return -1; -} - - -int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs) -{ - if (!length) - bzero(ptr, Field_blob::pack_length()); - else - { - if (from == Geometry::bad_geometry_data.ptr()) - goto err; - // Check given WKB - uint32 wkb_type; - if (length < SRID_SIZE + WKB_HEADER_SIZE + 4) - goto err; - wkb_type= uint4korr(from + SRID_SIZE + 1); - if (wkb_type < (uint32) Geometry::wkb_point || - wkb_type > (uint32) Geometry::wkb_last) - goto err; - - if (m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRY && - m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRYCOLLECTION && - (uint32) m_type_handler->geometry_type() != wkb_type) - { - const char *db= table->s->db.str; - const char *tab_name= table->s->table_name.str; - - if (!db) - db= ""; - if (!tab_name) - tab_name= ""; - - my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0), - Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str, - Geometry::ci_collection[wkb_type]->m_name.str, - db, tab_name, field_name.str, - (ulong) table->in_use->get_stmt_da()-> - current_row_for_warning()); - goto err_exit; - } - - Field_blob::store_length(length); - if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) && - from != value.ptr()) - { // Must make a copy - value.copy(from, length, cs); - from= value.ptr(); - } - bmove(ptr + packlength, &from, sizeof(char*)); - } - return 0; - -err: - my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, - ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); -err_exit: - bzero(ptr, Field_blob::pack_length()); - return -1; -} - - -bool Field_geom::is_equal(const Column_definition &new_field) const -{ - /* - - Allow ALTER..INPLACE to supertype (GEOMETRY), - e.g. POINT to GEOMETRY or POLYGON to GEOMETRY. - - Allow ALTER..INPLACE to the same geometry type: POINT -> POINT - */ - if (new_field.type_handler() == m_type_handler) - return true; - const Type_handler_geometry *gth= - dynamic_cast(new_field.type_handler()); - return gth && gth->is_binary_compatible_geom_super_type_for(m_type_handler); -} - - -bool Field_geom::can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const -{ - return item->cmp_type() == STRING_RESULT; -} - - -bool Field_geom::load_data_set_no_data(THD *thd, bool fixed_format) -{ - return Field_geom::load_data_set_null(thd); -} - - -bool Field_geom::load_data_set_null(THD *thd) -{ - Field_blob::reset(); - if (!maybe_null()) - { - my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field_name.str, - thd->get_stmt_da()->current_row_for_warning()); - return true; - } - set_null(); - set_has_explicit_value(); // Do not auto-update this field - return false; -} - - -#endif /*HAVE_SPATIAL*/ - /**************************************************************************** ** enum type. ** This is a string which only can have a selection of different values. diff --git a/sql/field.h b/sql/field.h index 3653f4e1e92..0923e2786e9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -32,7 +32,6 @@ #include "sql_error.h" /* Sql_condition */ #include "compat56.h" #include "sql_type.h" /* Type_std_attributes */ -#include "sql_type_geom.h" #include "field_comp.h" class Send_field; @@ -4226,120 +4225,6 @@ private: }; -#ifdef HAVE_SPATIAL -class Field_geom :public Field_blob -{ - const Type_handler_geometry *m_type_handler; -public: - uint srid; - uint precision; - enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1}; - enum storage_type storage; - - Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - TABLE_SHARE *share, uint blob_pack_length, - const Type_handler_geometry *gth, - uint field_srid) - :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, share, blob_pack_length, &my_charset_bin), - m_type_handler(gth) - { srid= field_srid; } - enum_conv_type rpl_conv_type_from(const Conv_source &source, - const Relay_log_info *rli, - const Conv_param ¶m) const; - enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; } - const Type_handler *type_handler() const - { - return m_type_handler; - } - const Type_handler_geometry *type_handler_geom() const - { - return m_type_handler; - } - void set_type_handler(const Type_handler_geometry *th) - { - m_type_handler= th; - } - enum_field_types type() const - { - return MYSQL_TYPE_GEOMETRY; - } - enum_field_types real_type() const - { - return MYSQL_TYPE_GEOMETRY; - } - Information_schema_character_attributes - information_schema_character_attributes() const - { - return Information_schema_character_attributes(); - } - void make_send_field(Send_field *to) - { - Field_longstr::make_send_field(to); - } - bool can_optimize_range(const Item_bool_func *cond, - const Item *item, - bool is_eq_func) const; - void sql_type(String &str) const; - Copy_func *get_copy_func(const Field *from) const - { - const Type_handler_geometry *fth= - dynamic_cast(from->type_handler()); - if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth)) - return get_identical_copy_func(); - return do_conv_blob; - } - bool memcpy_field_possible(const Field *from) const - { - const Type_handler_geometry *fth= - dynamic_cast(from->type_handler()); - return fth && - m_type_handler->is_binary_compatible_geom_super_type_for(fth) && - !table->copy_blobs; - } - bool is_equal(const Column_definition &new_field) const; - bool can_be_converted_by_engine(const Column_definition &new_type) const - { - return table->file->can_convert_geom(this, new_type); - } - - int store(const char *to, size_t length, CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr, bool unsigned_val); - int store_decimal(const my_decimal *); - uint size_of() const { return sizeof(*this); } - /** - Key length is provided only to support hash joins. (compared byte for byte) - Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2. - - The comparison is not very relevant, as identical geometry might be - represented differently, but we need to support it either way. - */ - uint32 key_length() const { return packlength; } - - /** - Non-nullable GEOMETRY types cannot have defaults, - but the underlying blob must still be reset. - */ - int reset(void) { return Field_blob::reset() || !maybe_null(); } - bool load_data_set_null(THD *thd); - bool load_data_set_no_data(THD *thd, bool fixed_format); - - uint get_srid() const { return srid; } - void print_key_value(String *out, uint32 length) - { - out->append(STRING_WITH_LEN("unprintable_geometry_value")); - } -}; - -uint gis_field_options_image(uchar *buff, List &create_fields); -uint gis_field_options_read(const uchar *buf, size_t buf_len, - Field_geom::storage_type *st_type,uint *precision, uint *scale, uint *srid); - -#endif /*HAVE_SPATIAL*/ - - class Field_enum :public Field_str { static void do_field_enum(Copy_field *copy_field); protected: diff --git a/sql/handler.h b/sql/handler.h index 3407321bac1..d7061ff9504 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -52,7 +52,6 @@ class Rowid_filter; class Field_string; class Field_varstring; class Field_blob; -class Field_geom; class Column_definition; // the following is for checking tables @@ -4818,11 +4817,6 @@ public: { return false; } - virtual bool can_convert_geom(const Field_geom *field, - const Column_definition &new_type) const - { - return false; - } protected: Handler_share *get_ha_share_ptr(); diff --git a/sql/item.h b/sql/item.h index 79b76e61207..ae96d67ebfd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5792,7 +5792,6 @@ public: #include "item_row.h" #include "item_cmpfunc.h" #include "item_strfunc.h" -#include "item_geofunc.h" #include "item_timefunc.h" #include "item_subselect.h" #include "item_xmlfunc.h" diff --git a/sql/item_create.cc b/sql/item_create.cc index 32c5dce8a8d..5420ec7bf5f 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -35,6 +35,7 @@ #include "sp.h" #include "item_inetfunc.h" #include "sql_time.h" +#include "sql_type_geom.h" /* ============================================================================= diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 934835abd4f..4cec7dd0f26 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -38,6 +38,7 @@ #ifdef HAVE_SPATIAL #include #include "opt_range.h" +#include "item_geofunc.h" bool Item_geometry_func::fix_length_and_dec() diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index e1fbe278063..f3d4c4bc38f 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -26,6 +26,8 @@ #pragma interface /* gcc class implementation */ #endif +#include "sql_type_geom.h" +#include "item.h" #include "gcalc_slicescan.h" #include "gcalc_tools.h" diff --git a/sql/sql_type.h b/sql/sql_type.h index f57791968ce..73e6ab5924f 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3484,6 +3484,12 @@ public: { return false; } + virtual uint Column_definition_gis_options_image(uchar *buff, + const Column_definition &def) + const + { + return 0; + } // Check if the implicit default value is Ok in the current sql_mode virtual bool validate_implicit_default_value(THD *thd, const Column_definition &def) diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc index 31e6f318b91..120306a58a2 100644 --- a/sql/sql_type_geom.cc +++ b/sql/sql_type_geom.cc @@ -15,12 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "sql_type_geom.h" -#include "sql_class.h" -#include "item.h" +#include "mariadb.h" #ifdef HAVE_SPATIAL +#include "sql_class.h" +#include "sql_type_geom.h" +#include "item_geofunc.h" + const Name Type_handler_geometry:: m_name_geometry(STRING_WITH_LEN("geometry")), @@ -619,6 +621,97 @@ void Type_handler_geometry:: } + +/* Values 1-40 reserved for 1-byte options, + 41-80 for 2-byte options, + 81-120 for 4-byte options, + 121-160 for 8-byte options, + other - varied length in next 1-3 bytes. +*/ +enum extra2_gis_field_options { + FIELDGEOM_END=0, + FIELDGEOM_STORAGE_MODEL=1, + FIELDGEOM_PRECISION=2, + FIELDGEOM_SCALE=3, + FIELDGEOM_SRID=81, +}; + + +uint +Type_handler_geometry:: + Column_definition_gis_options_image(uchar *cbuf, + const Column_definition &def) const +{ + if (cbuf) + { + cbuf[0]= FIELDGEOM_STORAGE_MODEL; + cbuf[1]= (uchar) Field_geom::GEOM_STORAGE_WKB; + + cbuf[2]= FIELDGEOM_PRECISION; + cbuf[3]= (uchar) def.length; + + cbuf[4]= FIELDGEOM_SCALE; + cbuf[5]= (uchar) def.decimals; + + cbuf[6]= FIELDGEOM_SRID; + int4store(cbuf + 7, ((uint32) def.srid)); + + cbuf[11]= FIELDGEOM_END; + } + return 12; +} + + +static uint gis_field_options_read(const uchar *buf, size_t buf_len, + Field_geom::storage_type *st_type, + uint *precision, uint *scale, uint *srid) +{ + const uchar *buf_end= buf + buf_len; + const uchar *cbuf= buf; + int option_id; + + *precision= *scale= *srid= 0; + *st_type= Field_geom::GEOM_STORAGE_WKB; + + if (!buf) /* can only happen with the old FRM file */ + goto end_of_record; + + while (cbuf < buf_end) + { + switch ((option_id= *(cbuf++))) + { + case FIELDGEOM_STORAGE_MODEL: + *st_type= (Field_geom::storage_type) cbuf[0]; + break; + case FIELDGEOM_PRECISION: + *precision= cbuf[0]; + break; + case FIELDGEOM_SCALE: + *scale= cbuf[0]; + break; + case FIELDGEOM_SRID: + *srid= uint4korr(cbuf); + break; + case FIELDGEOM_END: + goto end_of_record; + } + if (option_id > 0 && option_id <= 40) + cbuf+= 1; + else if (option_id > 40 && option_id <= 80) + cbuf+= 2; + else if (option_id > 80 && option_id <= 120) + cbuf+= 4; + else if (option_id > 120 && option_id <= 160) + cbuf+= 8; + else /* > 160 and <=255 */ + cbuf+= cbuf[0] ? 1 + cbuf[0] : 3 + uint2korr(cbuf+1); + } + +end_of_record: + return (uint)(cbuf - buf); +} + + bool Type_handler_geometry:: Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, TABLE_SHARE *share, @@ -658,4 +751,139 @@ Field_geom::rpl_conv_type_from(const Conv_source &source, } +/*****************************************************************/ +void Field_geom::sql_type(String &res) const +{ + CHARSET_INFO *cs= &my_charset_latin1; + const Name tmp= m_type_handler->name(); + res.set(tmp.ptr(), tmp.length(), cs); +} + + +int Field_geom::store(double nr) +{ + my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, + ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); + return -1; +} + + +int Field_geom::store(longlong nr, bool unsigned_val) +{ + my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, + ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); + return -1; +} + + +int Field_geom::store_decimal(const my_decimal *) +{ + my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, + ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); + return -1; +} + + +int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs) +{ + if (!length) + bzero(ptr, Field_blob::pack_length()); + else + { + if (from == Geometry::bad_geometry_data.ptr()) + goto err; + // Check given WKB + uint32 wkb_type; + if (length < SRID_SIZE + WKB_HEADER_SIZE + 4) + goto err; + wkb_type= uint4korr(from + SRID_SIZE + 1); + if (wkb_type < (uint32) Geometry::wkb_point || + wkb_type > (uint32) Geometry::wkb_last) + goto err; + + if (m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRY && + m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRYCOLLECTION && + (uint32) m_type_handler->geometry_type() != wkb_type) + { + const char *db= table->s->db.str; + const char *tab_name= table->s->table_name.str; + + if (!db) + db= ""; + if (!tab_name) + tab_name= ""; + + my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0), + Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str, + Geometry::ci_collection[wkb_type]->m_name.str, + db, tab_name, field_name.str, + (ulong) table->in_use->get_stmt_da()-> + current_row_for_warning()); + goto err_exit; + } + + Field_blob::store_length(length); + if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) && + from != value.ptr()) + { // Must make a copy + value.copy(from, length, cs); + from= value.ptr(); + } + bmove(ptr + packlength, &from, sizeof(char*)); + } + return 0; + +err: + my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, + ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); +err_exit: + bzero(ptr, Field_blob::pack_length()); + return -1; +} + + +bool Field_geom::is_equal(const Column_definition &new_field) const +{ + /* + - Allow ALTER..INPLACE to supertype (GEOMETRY), + e.g. POINT to GEOMETRY or POLYGON to GEOMETRY. + - Allow ALTER..INPLACE to the same geometry type: POINT -> POINT + */ + if (new_field.type_handler() == m_type_handler) + return true; + const Type_handler_geometry *gth= + dynamic_cast(new_field.type_handler()); + return gth && gth->is_binary_compatible_geom_super_type_for(m_type_handler); +} + + +bool Field_geom::can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const +{ + return item->cmp_type() == STRING_RESULT; +} + + +bool Field_geom::load_data_set_no_data(THD *thd, bool fixed_format) +{ + return Field_geom::load_data_set_null(thd); +} + + +bool Field_geom::load_data_set_null(THD *thd) +{ + Field_blob::reset(); + if (!maybe_null()) + { + my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field_name.str, + thd->get_stmt_da()->current_row_for_warning()); + return true; + } + set_null(); + set_has_explicit_value(); // Do not auto-update this field + return false; +} + + #endif // HAVE_SPATIAL diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index 444db71d62f..d0b504d6844 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -72,6 +72,9 @@ public: const st_value *value) const override; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const override; + uint Column_definition_gis_options_image(uchar *buff, + const Column_definition &def) + const override; void Column_definition_attributes_frm_pack(const Column_definition_attributes *at, uchar *buff) const override; @@ -316,6 +319,115 @@ extern MYSQL_PLUGIN_IMPORT extern MYSQL_PLUGIN_IMPORT Type_collection_geometry type_collection_geometry; + +#include "field.h" + +class Field_geom :public Field_blob +{ + const Type_handler_geometry *m_type_handler; +public: + uint srid; + uint precision; + enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1}; + enum storage_type storage; + + Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share, uint blob_pack_length, + const Type_handler_geometry *gth, + uint field_srid) + :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, + field_name_arg, share, blob_pack_length, &my_charset_bin), + m_type_handler(gth) + { srid= field_srid; } + enum_conv_type rpl_conv_type_from(const Conv_source &source, + const Relay_log_info *rli, + const Conv_param ¶m) const; + enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; } + const Type_handler *type_handler() const + { + return m_type_handler; + } + const Type_handler_geometry *type_handler_geom() const + { + return m_type_handler; + } + void set_type_handler(const Type_handler_geometry *th) + { + m_type_handler= th; + } + enum_field_types type() const + { + return MYSQL_TYPE_GEOMETRY; + } + enum_field_types real_type() const + { + return MYSQL_TYPE_GEOMETRY; + } + Information_schema_character_attributes + information_schema_character_attributes() const + { + return Information_schema_character_attributes(); + } + void make_send_field(Send_field *to) + { + Field_longstr::make_send_field(to); + } + bool can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const; + void sql_type(String &str) const; + Copy_func *get_copy_func(const Field *from) const + { + const Type_handler_geometry *fth= + dynamic_cast(from->type_handler()); + if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth)) + return get_identical_copy_func(); + return do_conv_blob; + } + bool memcpy_field_possible(const Field *from) const + { + const Type_handler_geometry *fth= + dynamic_cast(from->type_handler()); + return fth && + m_type_handler->is_binary_compatible_geom_super_type_for(fth) && + !table->copy_blobs; + } + bool is_equal(const Column_definition &new_field) const; + bool can_be_converted_by_engine(const Column_definition &new_type) const + { + return false; // Override the Field_blob behavior + } + + int store(const char *to, size_t length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr, bool unsigned_val); + int store_decimal(const my_decimal *); + uint size_of() const { return sizeof(*this); } + /** + Key length is provided only to support hash joins. (compared byte for byte) + Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2. + + The comparison is not very relevant, as identical geometry might be + represented differently, but we need to support it either way. + */ + uint32 key_length() const { return packlength; } + + /** + Non-nullable GEOMETRY types cannot have defaults, + but the underlying blob must still be reset. + */ + int reset(void) { return Field_blob::reset() || !maybe_null(); } + bool load_data_set_null(THD *thd); + bool load_data_set_no_data(THD *thd, bool fixed_format); + + uint get_srid() const { return srid; } + void print_key_value(String *out, uint32 length) + { + out->append(STRING_WITH_LEN("unprintable_geometry_value")); + } +}; + #endif // HAVE_SPATIAL #endif // SQL_TYPE_GEOM_H_INCLUDED diff --git a/sql/unireg.cc b/sql/unireg.cc index 9cfd8159874..b82927a9d47 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -152,6 +152,25 @@ static size_t extra2_str_size(size_t len) return (len > 255 ? 3 : 1) + len; } + +static uint gis_field_options_image(uchar *buff, + List &create_fields) +{ + uint image_size= 0; + List_iterator it(create_fields); + Create_field *field; + while ((field= it++)) + { + if (field->real_field_type() != MYSQL_TYPE_GEOMETRY) + continue; + uchar *cbuf= buff ? buff + image_size : NULL; + image_size+= field->type_handler()-> + Column_definition_gis_options_image(cbuf, *field); + } + return image_size; +} + + /** Create a frm (table definition) file @@ -241,9 +260,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, options_len= engine_table_options_frm_length(create_info->option_list, create_fields, keys, key_info); -#ifdef HAVE_SPATIAL gis_extra2_len= gis_field_options_image(NULL, create_fields); -#endif /*HAVE_SPATIAL*/ DBUG_PRINT("info", ("Options length: %u", options_len)); if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, @@ -356,14 +373,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, create_fields, keys, key_info); } -#ifdef HAVE_SPATIAL if (gis_extra2_len) { *pos= EXTRA2_GIS; pos= extra2_write_len(pos+1, gis_extra2_len); pos+= gis_field_options_image(pos, create_fields); } -#endif /*HAVE_SPATIAL*/ // PERIOD if (create_info->period_info.is_set()) diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 35597d8d2e9..810762e53a0 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -6089,7 +6089,7 @@ int ha_mroonga::storage_write_row(uchar *buf) #ifdef MRN_HAVE_SPATIAL bool is_null_geometry_value = field->real_type() == MYSQL_TYPE_GEOMETRY && - static_cast(field)->get_length() == 0; + static_cast(field)->get_length() == 0; if (is_null_geometry_value) { continue; } @@ -10729,7 +10729,7 @@ int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf) int error = 0; #ifdef MRN_HAVE_SPATIAL String buffer; - Field_geom *geometry = (Field_geom *)field; + Field_blob *geometry = (Field_blob *)field; String *value = geometry->val_str(0, &buffer); const char *wkb = value->ptr(); int len = value->length(); @@ -11199,7 +11199,7 @@ void ha_mroonga::storage_store_field_geometry(Field *field, String *geometry_buffer = &blob_buffers[field->field_index]; geometry_buffer->length(0); uint wkb_length = sizeof(wkb) / sizeof(*wkb); - Field_geom *geometry = (Field_geom *)field; + Field_blob *geometry= (Field_blob *)field; geometry_buffer->reserve(wkb_length); geometry_buffer->q_append((const char *) wkb, wkb_length); geometry->set_ptr((uint32) wkb_length, (uchar *) geometry_buffer->ptr());