diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 34126c50bc9..3fd792c408a 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -114,6 +114,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/compat56.cc ../sql/sql_type.cc ../sql/sql_type.h ../sql/sql_type_json.cc + ../sql/sql_type_geom.cc ../sql/table_cache.cc ../sql/mf_iocache_encr.cc ../sql/item_inetfunc.cc ../sql/wsrep_dummy.cc ../sql/encryption.cc diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 87e7d0a0238..d8ca18b86e1 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -136,6 +136,7 @@ SET (SQL_SOURCE semisync.cc semisync_master.cc semisync_slave.cc semisync_master_ack_receiver.cc sql_type.cc sql_type_json.cc + sql_type_geom.cc item_windowfunc.cc sql_window.cc sql_cte.cc item_vers.cc diff --git a/sql/field.h b/sql/field.h index baa11876b46..9a581c83a14 100644 --- a/sql/field.h +++ b/sql/field.h @@ -32,6 +32,7 @@ #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; diff --git a/sql/rpl_utility_server.cc b/sql/rpl_utility_server.cc index 4f6f0f6f303..f3b11e46fa0 100644 --- a/sql/rpl_utility_server.cc +++ b/sql/rpl_utility_server.cc @@ -736,27 +736,6 @@ Field_null::rpl_conv_type_from(const Conv_source &source, } -#ifdef HAVE_SPATIAL -uint32 -Type_handler_geometry::max_display_length_for_field(const Conv_source &src) - const -{ - return (uint32) my_set_bits(4 * 8); -} - - -enum_conv_type -Field_geom::rpl_conv_type_from(const Conv_source &source, - const Relay_log_info *rli, - const Conv_param ¶m) const -{ - return binlog_type() == source.real_field_type() ? - rpl_conv_type_from_same_data_type(source.metadata(), rli, param) : - CONV_TYPE_IMPOSSIBLE; -} -#endif // HAVE_SPATIAL - - /**********************************************************************/ diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 9f6bbc3e992..b912197103f 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -16,6 +16,7 @@ #include "mariadb.h" #include "sql_type.h" +#include "sql_type_geom.h" #include "sql_const.h" #include "sql_class.h" #include "sql_time.h" @@ -74,6 +75,10 @@ Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff; class Type_collection_std: public Type_collection { public: + bool init(Type_handler_data *data) override + { + return false; + } const Type_handler *handler_by_name(const LEX_CSTRING &name) const override { return NULL; @@ -104,167 +109,6 @@ const Type_collection *Type_handler::type_collection() const } -#ifdef HAVE_SPATIAL -Type_handler_geometry type_handler_geometry; -Type_handler_point type_handler_point; -Type_handler_linestring type_handler_linestring; -Type_handler_polygon type_handler_polygon; -Type_handler_multipoint type_handler_multipoint; -Type_handler_multilinestring type_handler_multilinestring; -Type_handler_multipolygon type_handler_multipolygon; -Type_handler_geometrycollection type_handler_geometrycollection; - - -const Type_handler_geometry * -Type_handler_geometry::type_handler_geom_by_type(uint type) -{ - switch (type) { - case Type_handler_geometry::GEOM_POINT: - return &type_handler_point; - case Type_handler_geometry::GEOM_LINESTRING: - return &type_handler_linestring; - case Type_handler_geometry::GEOM_POLYGON: - return &type_handler_polygon; - case Type_handler_geometry::GEOM_MULTIPOINT: - return &type_handler_multipoint; - case Type_handler_geometry::GEOM_MULTILINESTRING: - return &type_handler_multilinestring; - case Type_handler_geometry::GEOM_MULTIPOLYGON: - return &type_handler_multipolygon; - case Type_handler_geometry::GEOM_GEOMETRYCOLLECTION: - return &type_handler_geometrycollection; - case Type_handler_geometry::GEOM_GEOMETRY: - break; - } - return &type_handler_geometry; -} - - -const Type_handler * -Type_handler_geometry::type_handler_frm_unpack(const uchar *buffer) const -{ - // charset and geometry_type share the same byte in frm - return type_handler_geom_by_type((uint) buffer[14]); -} - - -class Type_collection_geometry: public Type_collection -{ - const Type_handler *aggregate_common(const Type_handler *a, - const Type_handler *b) const - { - if (a == b) - return a; - DBUG_ASSERT(dynamic_cast(a)); - DBUG_ASSERT(dynamic_cast(b)); - return &type_handler_geometry; - } -public: - const Type_handler *aggregate_for_result(const Type_handler *a, - const Type_handler *b) - const override - { - return aggregate_common(a, b); - } - const Type_handler *aggregate_for_comparison(const Type_handler *a, - const Type_handler *b) - const override - { - return aggregate_common(a, b); - } - const Type_handler *aggregate_for_min_max(const Type_handler *a, - const Type_handler *b) - const override - { - return aggregate_common(a, b); - } - const Type_handler *aggregate_for_num_op(const Type_handler *a, - const Type_handler *b) - const override - { - return NULL; - } - bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const - { - Type_aggregator *r= &data->m_type_aggregator_for_result; - Type_aggregator *c= &data->m_type_aggregator_for_comparison; - return - r->add(geom, &type_handler_null, geom) || - r->add(geom, &type_handler_hex_hybrid, &type_handler_long_blob) || - r->add(geom, &type_handler_tiny_blob, &type_handler_long_blob) || - r->add(geom, &type_handler_blob, &type_handler_long_blob) || - r->add(geom, &type_handler_medium_blob, &type_handler_long_blob) || - r->add(geom, &type_handler_long_blob, &type_handler_long_blob) || - r->add(geom, &type_handler_varchar, &type_handler_long_blob) || - r->add(geom, &type_handler_string, &type_handler_long_blob) || - c->add(geom, &type_handler_null, geom) || - c->add(geom, &type_handler_long_blob, &type_handler_long_blob); - } - bool init(Type_handler_data *data) const - { -#ifndef DBUG_OFF - /* - The rules (geometry,geometry)->geometry and (pont,point)->geometry - are needed here to make sure - (in gis-debug.test) that they do not affect anything, and these pairs - returns an error in an expression like (POINT(0,0)+POINT(0,0)). - Both sides are from the same type collection here, - so aggregation goes only through Type_collection_xxx::aggregate_yyy() - and never reaches Type_aggregator::find_handler(). - */ - Type_aggregator *nct= &data->m_type_aggregator_non_commutative_test; - if (nct->add(&type_handler_geometry, - &type_handler_geometry, - &type_handler_geometry) || - nct->add(&type_handler_point, - &type_handler_point, - &type_handler_geometry) || - nct->add(&type_handler_point, - &type_handler_varchar, - &type_handler_long_blob)) - return true; -#endif - return - init_aggregators(data, &type_handler_geometry) || - init_aggregators(data, &type_handler_geometrycollection) || - init_aggregators(data, &type_handler_point) || - init_aggregators(data, &type_handler_linestring) || - init_aggregators(data, &type_handler_polygon) || - init_aggregators(data, &type_handler_multipoint) || - init_aggregators(data, &type_handler_multilinestring) || - init_aggregators(data, &type_handler_multipolygon); - } - const Type_handler *handler_by_name(const LEX_CSTRING &name) const override - { - if (type_handler_point.name().eq(name)) - return &type_handler_point; - if (type_handler_linestring.name().eq(name)) - return &type_handler_linestring; - if (type_handler_polygon.name().eq(name)) - return &type_handler_polygon; - if (type_handler_multipoint.name().eq(name)) - return &type_handler_multipoint; - if (type_handler_multilinestring.name().eq(name)) - return &type_handler_multilinestring; - if (type_handler_multipolygon.name().eq(name)) - return &type_handler_multipolygon; - if (type_handler_geometry.name().eq(name)) - return &type_handler_geometry; - if (type_handler_geometrycollection.name().eq(name)) - return &type_handler_geometrycollection; - return NULL; - } -}; - - -static Type_collection_geometry type_collection_geometry; - -const Type_collection *Type_handler_geometry::type_collection() const -{ - return &type_collection_geometry; -} - -#endif bool Type_handler_data::init() @@ -2448,78 +2292,6 @@ Field *Type_handler_blob_compressed::make_conversion_table_field(TABLE *table, } -#ifdef HAVE_SPATIAL - -bool Type_handler_geometry::check_type_geom_or_binary(const char *opname, - const Item *item) -{ - const Type_handler *handler= item->type_handler(); - if (handler->type_handler_for_comparison() == &type_handler_geometry || - (handler->is_general_purpose_string_type() && - item->collation.collation == &my_charset_bin)) - return false; - my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0), - handler->name().ptr(), opname); - return true; -} - - -bool Type_handler_geometry::check_types_geom_or_binary(const char *opname, - Item* const *args, - uint start, uint end) -{ - for (uint i= start; i < end ; i++) - { - if (check_type_geom_or_binary(opname, args[i])) - return true; - } - return false; -} - - -const Name - Type_handler_geometry:: - m_name_geometry(STRING_WITH_LEN("geometry")), - Type_handler_point:: - m_name_point(STRING_WITH_LEN("point")), - Type_handler_linestring:: - m_name_linestring(STRING_WITH_LEN("linestring")), - Type_handler_polygon:: - m_name_polygon(STRING_WITH_LEN("polygon")), - Type_handler_multipoint:: - m_name_multipoint(STRING_WITH_LEN("multipoint")), - Type_handler_multilinestring:: - m_name_multilinestring(STRING_WITH_LEN("multilinestring")), - Type_handler_multipolygon:: - m_name_multipolygon(STRING_WITH_LEN("multipolygon")), - Type_handler_geometrycollection:: - m_name_geometrycollection(STRING_WITH_LEN("geometrycollection")); - -const Type_handler *Type_handler_geometry::type_handler_for_comparison() const -{ - return &type_handler_geometry; -} - - -Field *Type_handler_geometry::make_conversion_table_field(TABLE *table, - uint metadata, - const Field *target) - const -{ - DBUG_ASSERT(target->type() == MYSQL_TYPE_GEOMETRY); - /* - We do not do not update feature_gis statistics here: - status_var_increment(target->table->in_use->status_var.feature_gis); - as this is only a temporary field. - The statistics was already incremented when "target" was created. - */ - const Field_geom *fg= static_cast(target); - return new(table->in_use->mem_root) - Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, - table->s, 4, fg->type_handler_geom(), fg->srid); -} -#endif - Field *Type_handler_enum::make_conversion_table_field(TABLE *table, uint metadata, const Field *target) @@ -2662,14 +2434,6 @@ bool Type_handler_blob_common:: return def->check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_BLOBLENGTH); } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Column_definition_fix_attributes(Column_definition *def) const -{ - def->flags|= BLOB_FLAG; - return false; -} -#endif bool Type_handler_year:: Column_definition_fix_attributes(Column_definition *def) const @@ -2762,17 +2526,6 @@ void Type_handler_typelib:: } -#ifdef HAVE_SPATIAL -void Type_handler_geometry:: - Column_definition_reuse_fix_attributes(THD *thd, - Column_definition *def, - const Field *field) const -{ - def->srid= ((Field_geom*) field)->srid; -} -#endif - - void Type_handler_year:: Column_definition_reuse_fix_attributes(THD *thd, Column_definition *def, @@ -2882,20 +2635,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Column_definition_prepare_stage1(THD *thd, - MEM_ROOT *mem_root, - Column_definition *def, - handler *file, - ulonglong table_flags) const -{ - def->create_length_to_internal_length_string(); - return def->prepare_blob_field(thd); -} -#endif - - /*************************************************************************/ bool Type_handler:: @@ -3036,21 +2775,6 @@ bool Type_handler_blob_common:: return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_BLOB); } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Column_definition_prepare_stage2(Column_definition *def, - handler *file, - ulonglong table_flags) const -{ - if (!(table_flags & HA_CAN_GEOMETRY)) - { - my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY"); - return true; - } - return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_GEOM); -} -#endif - bool Type_handler_varchar:: Column_definition_prepare_stage2(Column_definition *def, handler *file, @@ -3192,164 +2916,6 @@ bool Type_handler_blob_common::Key_part_spec_init_foreign(Key_part_spec *part, } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry::Key_part_spec_init_primary(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - return part->check_primary_key_for_blob(file); -} - - -bool Type_handler_geometry::Key_part_spec_init_unique(Key_part_spec *part, - const Column_definition &def, - const handler *file, - bool *hash_field_needed) const -{ - if (!part->length) - *hash_field_needed= true; - return part->check_key_for_blob(file); -} - - -bool Type_handler_geometry::Key_part_spec_init_multiple(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - return part->init_multiple_key_for_blob(file); -} - - -bool Type_handler_geometry::Key_part_spec_init_foreign(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - return part->check_foreign_key_for_blob(file); -} - - -bool Type_handler_geometry::Key_part_spec_init_spatial(Key_part_spec *part, - const Column_definition &def) - const -{ - if (part->length) - { - my_error(ER_WRONG_SUB_KEY, MYF(0)); - return true; - } - /* - 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case - Lately we'll extend this code to support more dimensions - */ - part->length= 4 * sizeof(double); - return false; -} - - -bool Type_handler_point::Key_part_spec_init_primary(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - /* - QQ: - The below assignment (here and in all other Key_part_spec_init_xxx methods) - overrides the explicitly given key part length, so in this query: - CREATE OR REPLACE TABLE t1 (a POINT, KEY(a(10))); - the key becomes KEY(a(25)). - This might be a bug. - */ - part->length= octet_length(); - return part->check_key_for_blob(file); -} - - -bool Type_handler_point::Key_part_spec_init_unique(Key_part_spec *part, - const Column_definition &def, - const handler *file, - bool *hash_field_needed) const -{ - part->length= octet_length(); - return part->check_key_for_blob(file); -} - - -bool Type_handler_point::Key_part_spec_init_multiple(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - part->length= octet_length(); - return part->check_key_for_blob(file); -} - - -bool Type_handler_point::Key_part_spec_init_foreign(Key_part_spec *part, - const Column_definition &def, - const handler *file) const -{ - part->length= octet_length(); - return part->check_key_for_blob(file); -} - - -Item * -Type_handler_point::make_constructor_item(THD *thd, List *args) const -{ - if (!args || args->elements != 2) - return NULL; - Item_args tmp(thd, *args); - return new (thd->mem_root) Item_func_point(thd, - tmp.arguments()[0], - tmp.arguments()[1]); -} - - -Item * -Type_handler_linestring::make_constructor_item(THD *thd, List *args) const -{ - return args ? new (thd->mem_root) Item_func_linestring(thd, *args) : NULL; -} - - -Item * -Type_handler_polygon::make_constructor_item(THD *thd, List *args) const -{ - return args ? new (thd->mem_root) Item_func_polygon(thd, *args) : NULL; -} - - -Item * -Type_handler_multipoint::make_constructor_item(THD *thd, List *args) const -{ - return args ? new (thd->mem_root) Item_func_multipoint(thd, *args) : NULL; -} - - -Item * -Type_handler_multilinestring::make_constructor_item(THD *thd, - List *args) const -{ - return args ? new (thd->mem_root) Item_func_multilinestring(thd, *args) : - NULL; -} - - -Item * -Type_handler_multipolygon::make_constructor_item(THD *thd, - List *args) const -{ - return args ? new (thd->mem_root) Item_func_multipolygon(thd, *args) : NULL; -} - - -Item * -Type_handler_geometrycollection::make_constructor_item(THD *thd, - List *args) const -{ - return args ? new (thd->mem_root) Item_func_geometrycollection(thd, *args) : - NULL; -} - -#endif // HAVE_SPATIAL /*************************************************************************/ @@ -3409,13 +2975,6 @@ uint32 Type_handler_long_blob::calc_pack_length(uint32 length) const return 4 + portable_sizeof_char_ptr; } -#ifdef HAVE_SPATIAL -uint32 Type_handler_geometry::calc_pack_length(uint32 length) const -{ - return 4 + portable_sizeof_char_ptr; -} -#endif - uint32 Type_handler_newdecimal::calc_pack_length(uint32 length) const { abort(); // This shouldn't happen @@ -3850,20 +3409,6 @@ Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name, } - -#ifdef HAVE_SPATIAL -Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name, - const Record_addr &addr, - const Type_all_attributes &attr, - TABLE *table) const -{ - return new (table->in_use->mem_root) - Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(), - Field::NONE, name, table->s, 4, this, 0); -} -#endif - - Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name, const Record_addr &addr, const Type_all_attributes &attr, @@ -4644,25 +4189,6 @@ bool Type_handler_timestamp_common:: return false; } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_hybrid_func_fix_attributes(THD *thd, - const char *func_name, - Type_handler_hybrid_field_type *handler, - Type_all_attributes *func, - Item **items, uint nitems) const -{ - DBUG_ASSERT(nitems > 0); - func->collation.set(&my_charset_bin); - func->unsigned_flag= false; - func->decimals= 0; - func->max_length= (uint32) UINT_MAX32; - func->set_maybe_null(true); - return false; -} -#endif - - /*************************************************************************/ bool Type_handler:: @@ -4941,13 +4467,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const -{ - return Item_func_or_sum_illegal_param("sum"); -} -#endif /*************************************************************************/ @@ -4992,13 +4511,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const -{ - return Item_func_or_sum_illegal_param("avg"); -} -#endif /*************************************************************************/ @@ -5043,15 +4555,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const -{ - return Item_func_or_sum_illegal_param(item); -} -#endif - - /*************************************************************************/ bool Type_handler_real_result::Item_val_bool(Item *item) const @@ -6330,14 +5833,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_func_round_fix_length_and_dec(Item_func_round *item) const -{ - return Item_func_or_sum_illegal_param(item); -} -#endif - /***************************************************************************/ bool Type_handler_row:: @@ -6388,14 +5883,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const -{ - return Item_func_or_sum_illegal_param(item); -} -#endif - /***************************************************************************/ bool Type_handler_row:: @@ -6446,14 +5933,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_func_abs_fix_length_and_dec(Item_func_abs *item) const -{ - return Item_func_or_sum_illegal_param(item); -} -#endif - /***************************************************************************/ bool Type_handler_row:: @@ -6504,15 +5983,6 @@ bool Type_handler_string_result:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Item_func_neg_fix_length_and_dec(Item_func_neg *item) const -{ - return Item_func_or_sum_illegal_param(item); -} -#endif - - /***************************************************************************/ bool Type_handler:: @@ -6662,78 +6132,6 @@ bool Type_handler:: } -#ifdef HAVE_SPATIAL - -bool Type_handler_geometry:: - Item_func_signed_fix_length_and_dec(Item_func_signed *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const -{ - if (item->cast_charset() != &my_charset_bin) - return Item_func_or_sum_illegal_param(item); // CAST(geom AS CHAR) - item->fix_length_and_dec_str(); - return false; // CAST(geom AS BINARY) -} - - -bool Type_handler_geometry:: - Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - - -bool Type_handler_geometry:: - Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const -{ - return Item_func_or_sum_illegal_param(item); -} - - -bool Type_handler_geometry:: - Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) - const -{ - return Item_func_or_sum_illegal_param(item); - -} - -#endif /* HAVE_SPATIAL */ - /***************************************************************************/ bool Type_handler_row:: @@ -7352,20 +6750,6 @@ bool Type_handler_temporal_result:: } -#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->setup_conversion_blob(thd); - return param->set_str(val->m_string.ptr(), val->m_string.length(), - &my_charset_bin, &my_charset_bin); -} -#endif - /***************************************************************************/ bool Type_handler_null:: @@ -7924,15 +7308,6 @@ void Type_handler_typelib::Item_param_set_param_func(Item_param *param, } -#ifdef HAVE_SPATIAL -void Type_handler_geometry::Item_param_set_param_func(Item_param *param, - uchar **pos, - ulong len) const -{ - param->set_null(); // Not possible type code in the client-server protocol -} -#endif - /***************************************************************************/ Field *Type_handler_row:: @@ -8256,21 +7631,6 @@ Field *Type_handler_bit:: } -#ifdef HAVE_SPATIAL -Field *Type_handler_geometry:: - make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, - const LEX_CSTRING *name, - const Record_addr &rec, const Bit_addr &bit, - const Column_definition_attributes *attr, - uint32 flags) const -{ - status_var_increment(current_thd->status_var.feature_gis); - return new (mem_root) - Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(), - attr->unireg_check, name, share, - attr->pack_flag_to_pack_length(), this, attr->srid); -} -#endif Field *Type_handler_string:: @@ -8368,16 +7728,6 @@ void Type_handler:: } -#ifdef HAVE_SPATIAL -void Type_handler_geometry:: - Column_definition_attributes_frm_pack(const Column_definition_attributes *def, - uchar *buff) const -{ - def->frm_pack_basic(buff); - buff[11]= 0; - buff[14]= (uchar) geometry_type(); -} -#endif /***************************************************************************/ @@ -8394,27 +7744,6 @@ bool Type_handler:: } -#ifdef HAVE_SPATIAL -bool Type_handler_geometry:: - Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, - TABLE_SHARE *share, - const uchar *buffer, - LEX_CUSTRING *gis_options) - const -{ - uint gis_opt_read, gis_length, gis_decimals; - Field_geom::storage_type st_type; - attr->frm_unpack_basic(buffer); - gis_opt_read= gis_field_options_read(gis_options->str, - gis_options->length, - &st_type, &gis_length, - &gis_decimals, &attr->srid); - gis_options->str+= gis_opt_read; - gis_options->length-= gis_opt_read; - return false; -} -#endif - /***************************************************************************/ bool Type_handler::Vers_history_point_resolve_unit(THD *thd, diff --git a/sql/sql_type.h b/sql/sql_type.h index dd765d876e4..dafec01b524 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -73,6 +73,7 @@ class Item_func_div; class Item_func_mod; class cmp_item; class in_vector; +class Type_handler_data; class Type_handler_hybrid_field_type; class Sort_param; class Arg_comparator; @@ -6414,234 +6415,6 @@ public: }; -#ifdef HAVE_SPATIAL -class Type_handler_geometry: public Type_handler_string_result -{ - static const Name m_name_geometry; -public: - enum geometry_types - { - GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3, - GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6, - GEOM_GEOMETRYCOLLECTION = 7 - }; - static bool check_type_geom_or_binary(const char *opname, const Item *item); - static bool check_types_geom_or_binary(const char *opname, - Item * const *args, - uint start, uint end); - static const Type_handler_geometry *type_handler_geom_by_type(uint type); -public: - virtual ~Type_handler_geometry() {} - const Name name() const override { return m_name_geometry; } - enum_field_types field_type() const override { return MYSQL_TYPE_GEOMETRY; } - bool is_param_long_data_type() const override { return true; } - uint32 max_display_length_for_field(const Conv_source &src) const override; - uint32 calc_pack_length(uint32 length) const override; - const Type_collection *type_collection() const override; - const Type_handler *type_handler_for_comparison() const override; - virtual geometry_types geometry_type() const { return GEOM_GEOMETRY; } - const Type_handler *type_handler_frm_unpack(const uchar *buffer) - const override; - bool is_binary_compatible_geom_super_type_for(const Type_handler_geometry *th) - const - { - return geometry_type() == GEOM_GEOMETRY || - geometry_type() == th->geometry_type(); - } - bool type_can_have_key_part() const override { return true; } - bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override - { - return false; // Materialization does not work with GEOMETRY columns - } - void Item_param_set_param_func(Item_param *param, - uchar **pos, ulong len) const override; - bool Item_param_set_from_value(THD *thd, - Item_param *param, - const Type_all_attributes *attr, - const st_value *value) const override; - Field *make_conversion_table_field(TABLE *, uint metadata, - const Field *target) const override; - void - Column_definition_attributes_frm_pack(const Column_definition_attributes *at, - uchar *buff) const override; - bool - Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, - TABLE_SHARE *share, - const uchar *buffer, - LEX_CUSTRING *gis_options) const - override; - bool Column_definition_fix_attributes(Column_definition *c) const override; - void Column_definition_reuse_fix_attributes(THD *thd, - Column_definition *c, - const Field *field) const - override; - bool Column_definition_prepare_stage1(THD *thd, - MEM_ROOT *mem_root, - Column_definition *c, - handler *file, - ulonglong table_flags) const override; - bool Column_definition_prepare_stage2(Column_definition *c, - handler *file, - ulonglong table_flags) const override; - bool Key_part_spec_init_primary(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; - bool Key_part_spec_init_unique(Key_part_spec *part, - const Column_definition &def, - const handler *file, - bool *has_key_needed) const override; - bool Key_part_spec_init_multiple(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; - bool Key_part_spec_init_foreign(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; - bool Key_part_spec_init_spatial(Key_part_spec *part, - const Column_definition &def) const override; - Field *make_table_field(const LEX_CSTRING *name, - const Record_addr &addr, - const Type_all_attributes &attr, - TABLE *table) const override; - - Field *make_table_field_from_def(TABLE_SHARE *share, - MEM_ROOT *mem_root, - const LEX_CSTRING *name, - const Record_addr &addr, - const Bit_addr &bit, - const Column_definition_attributes *attr, - uint32 flags) const override; - - bool can_return_int() const override { return false; } - bool can_return_decimal() const override { return false; } - bool can_return_real() const override { return false; } - bool can_return_text() const override { return false; } - bool can_return_date() const override { return false; } - bool can_return_time() const override { return false; } - bool is_traditional_type() const override { return false; } - bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; - bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; - bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; - bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; - bool Item_hybrid_func_fix_attributes(THD *thd, - const char *name, - Type_handler_hybrid_field_type *h, - Type_all_attributes *attr, - Item **items, uint nitems) const - override; - bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; - bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; - bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; - - bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override; - bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const - override; - bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const - override; - bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const - override; - bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const - override; - bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const - override; - bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const - override; - bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const - override; - bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const - override; -}; - - -class Type_handler_point: public Type_handler_geometry -{ - static const Name m_name_point; - // Binary length of a POINT value: 4 byte SRID + 21 byte WKB POINT - static uint octet_length() { return 25; } -public: - geometry_types geometry_type() const override { return GEOM_POINT; } - const Name name() const override { return m_name_point; } - Item *make_constructor_item(THD *thd, List *args) const override; - bool Key_part_spec_init_primary(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; - bool Key_part_spec_init_unique(Key_part_spec *part, - const Column_definition &def, - const handler *file, - bool *has_key_needed) const override; - bool Key_part_spec_init_multiple(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; - bool Key_part_spec_init_foreign(Key_part_spec *part, - const Column_definition &def, - const handler *file) const override; -}; - -class Type_handler_linestring: public Type_handler_geometry -{ - static const Name m_name_linestring; -public: - geometry_types geometry_type() const { return GEOM_LINESTRING; } - const Name name() const { return m_name_linestring; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -class Type_handler_polygon: public Type_handler_geometry -{ - static const Name m_name_polygon; -public: - geometry_types geometry_type() const { return GEOM_POLYGON; } - const Name name() const { return m_name_polygon; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -class Type_handler_multipoint: public Type_handler_geometry -{ - static const Name m_name_multipoint; -public: - geometry_types geometry_type() const { return GEOM_MULTIPOINT; } - const Name name() const { return m_name_multipoint; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -class Type_handler_multilinestring: public Type_handler_geometry -{ - static const Name m_name_multilinestring; -public: - geometry_types geometry_type() const { return GEOM_MULTILINESTRING; } - const Name name() const { return m_name_multilinestring; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -class Type_handler_multipolygon: public Type_handler_geometry -{ - static const Name m_name_multipolygon; -public: - geometry_types geometry_type() const { return GEOM_MULTIPOLYGON; } - const Name name() const { return m_name_multipolygon; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -class Type_handler_geometrycollection: public Type_handler_geometry -{ - static const Name m_name_geometrycollection; -public: - geometry_types geometry_type() const { return GEOM_GEOMETRYCOLLECTION; } - const Name name() const { return m_name_geometrycollection; } - Item *make_constructor_item(THD *thd, List *args) const override; -}; - -extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry; -extern MYSQL_PLUGIN_IMPORT Type_handler_point type_handler_point; -extern MYSQL_PLUGIN_IMPORT Type_handler_linestring type_handler_linestring; -extern MYSQL_PLUGIN_IMPORT Type_handler_polygon type_handler_polygon; -extern MYSQL_PLUGIN_IMPORT Type_handler_multipoint type_handler_multipoint; -extern MYSQL_PLUGIN_IMPORT Type_handler_multilinestring type_handler_multilinestring; -extern MYSQL_PLUGIN_IMPORT Type_handler_multipolygon type_handler_multipolygon; -extern MYSQL_PLUGIN_IMPORT Type_handler_geometrycollection type_handler_geometrycollection; -#endif - - class Type_handler_typelib: public Type_handler_general_purpose_string { public: @@ -6755,6 +6528,7 @@ class Type_collection { public: virtual ~Type_collection() {} + virtual bool init(Type_handler_data *data)= 0; virtual const Type_handler *handler_by_name(const LEX_CSTRING &name) const= 0; virtual const Type_handler *aggregate_for_result(const Type_handler *h1, const Type_handler *h2) diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc new file mode 100644 index 00000000000..31e6f318b91 --- /dev/null +++ b/sql/sql_type_geom.cc @@ -0,0 +1,661 @@ +/* + Copyright (c) 2015 MariaDB Foundation + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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" + +#ifdef HAVE_SPATIAL + +const Name + Type_handler_geometry:: + m_name_geometry(STRING_WITH_LEN("geometry")), + Type_handler_point:: + m_name_point(STRING_WITH_LEN("point")), + Type_handler_linestring:: + m_name_linestring(STRING_WITH_LEN("linestring")), + Type_handler_polygon:: + m_name_polygon(STRING_WITH_LEN("polygon")), + Type_handler_multipoint:: + m_name_multipoint(STRING_WITH_LEN("multipoint")), + Type_handler_multilinestring:: + m_name_multilinestring(STRING_WITH_LEN("multilinestring")), + Type_handler_multipolygon:: + m_name_multipolygon(STRING_WITH_LEN("multipolygon")), + Type_handler_geometrycollection:: + m_name_geometrycollection(STRING_WITH_LEN("geometrycollection")); + + +Type_handler_geometry type_handler_geometry; +Type_handler_point type_handler_point; +Type_handler_linestring type_handler_linestring; +Type_handler_polygon type_handler_polygon; +Type_handler_multipoint type_handler_multipoint; +Type_handler_multilinestring type_handler_multilinestring; +Type_handler_multipolygon type_handler_multipolygon; +Type_handler_geometrycollection type_handler_geometrycollection; + + +Type_collection_geometry type_collection_geometry; + + +const Type_handler_geometry * +Type_handler_geometry::type_handler_geom_by_type(uint type) +{ + switch (type) { + case Type_handler_geometry::GEOM_POINT: + return &type_handler_point; + case Type_handler_geometry::GEOM_LINESTRING: + return &type_handler_linestring; + case Type_handler_geometry::GEOM_POLYGON: + return &type_handler_polygon; + case Type_handler_geometry::GEOM_MULTIPOINT: + return &type_handler_multipoint; + case Type_handler_geometry::GEOM_MULTILINESTRING: + return &type_handler_multilinestring; + case Type_handler_geometry::GEOM_MULTIPOLYGON: + return &type_handler_multipolygon; + case Type_handler_geometry::GEOM_GEOMETRYCOLLECTION: + return &type_handler_geometrycollection; + case Type_handler_geometry::GEOM_GEOMETRY: + break; + } + return &type_handler_geometry; +} + + +const Type_handler * +Type_collection_geometry::handler_by_name(const LEX_CSTRING &name) const +{ + if (type_handler_point.name().eq(name)) + return &type_handler_point; + if (type_handler_linestring.name().eq(name)) + return &type_handler_linestring; + if (type_handler_polygon.name().eq(name)) + return &type_handler_polygon; + if (type_handler_multipoint.name().eq(name)) + return &type_handler_multipoint; + if (type_handler_multilinestring.name().eq(name)) + return &type_handler_multilinestring; + if (type_handler_multipolygon.name().eq(name)) + return &type_handler_multipolygon; + if (type_handler_geometry.name().eq(name)) + return &type_handler_geometry; + if (type_handler_geometrycollection.name().eq(name)) + return &type_handler_geometrycollection; + return NULL; +} + + +const Type_collection *Type_handler_geometry::type_collection() const +{ + return &type_collection_geometry; +} + + +const Type_handler * +Type_handler_geometry::type_handler_frm_unpack(const uchar *buffer) const +{ + // charset and geometry_type share the same byte in frm + return type_handler_geom_by_type((uint) buffer[14]); +} + + +bool Type_collection_geometry::init_aggregators(Type_handler_data *data, + const Type_handler *geom) const +{ + Type_aggregator *r= &data->m_type_aggregator_for_result; + Type_aggregator *c= &data->m_type_aggregator_for_comparison; + return + r->add(geom, &type_handler_null, geom) || + r->add(geom, &type_handler_hex_hybrid, &type_handler_long_blob) || + r->add(geom, &type_handler_tiny_blob, &type_handler_long_blob) || + r->add(geom, &type_handler_blob, &type_handler_long_blob) || + r->add(geom, &type_handler_medium_blob, &type_handler_long_blob) || + r->add(geom, &type_handler_long_blob, &type_handler_long_blob) || + r->add(geom, &type_handler_varchar, &type_handler_long_blob) || + r->add(geom, &type_handler_string, &type_handler_long_blob) || + c->add(geom, &type_handler_null, geom) || + c->add(geom, &type_handler_long_blob, &type_handler_long_blob); +} + + +bool Type_collection_geometry::init(Type_handler_data *data) +{ +#ifndef DBUG_OFF + /* + The rules (geometry,geometry)->geometry and (pont,point)->geometry + are needed here to make sure + (in gis-debug.test) that they do not affect anything, and these pairs + returns an error in an expression like (POINT(0,0)+POINT(0,0)). + Both sides are from the same type collection here, + so aggregation goes only through Type_collection_xxx::aggregate_yyy() + and never reaches Type_aggregator::find_handler(). + */ + Type_aggregator *nct= &data->m_type_aggregator_non_commutative_test; + if (nct->add(&type_handler_geometry, + &type_handler_geometry, + &type_handler_geometry) || + nct->add(&type_handler_point, + &type_handler_point, + &type_handler_geometry) || + nct->add(&type_handler_point, + &type_handler_varchar, + &type_handler_long_blob)) + return true; +#endif // DBUG_OFF + return + init_aggregators(data, &type_handler_geometry) || + init_aggregators(data, &type_handler_geometrycollection) || + init_aggregators(data, &type_handler_point) || + init_aggregators(data, &type_handler_linestring) || + init_aggregators(data, &type_handler_polygon) || + init_aggregators(data, &type_handler_multipoint) || + init_aggregators(data, &type_handler_multilinestring) || + init_aggregators(data, &type_handler_multipolygon); +} + + +bool Type_handler_geometry::check_type_geom_or_binary(const char *opname, + const Item *item) +{ + const Type_handler *handler= item->type_handler(); + if (handler->type_handler_for_comparison() == &type_handler_geometry || + (handler->is_general_purpose_string_type() && + item->collation.collation == &my_charset_bin)) + return false; + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0), + handler->name().ptr(), opname); + return true; +} + + +bool Type_handler_geometry::check_types_geom_or_binary(const char *opname, + Item* const *args, + uint start, uint end) +{ + for (uint i= start; i < end ; i++) + { + if (check_type_geom_or_binary(opname, args[i])) + return true; + } + return false; +} + + +const Type_handler *Type_handler_geometry::type_handler_for_comparison() const +{ + return &type_handler_geometry; +} + + +Field *Type_handler_geometry::make_conversion_table_field(TABLE *table, + uint metadata, + const Field *target) + const +{ + DBUG_ASSERT(target->type() == MYSQL_TYPE_GEOMETRY); + /* + We do not do not update feature_gis statistics here: + status_var_increment(target->table->in_use->status_var.feature_gis); + as this is only a temporary field. + The statistics was already incremented when "target" was created. + */ + const Field_geom *fg= static_cast(target); + return new(table->in_use->mem_root) + Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, + table->s, 4, fg->type_handler_geom(), fg->srid); +} + + +bool Type_handler_geometry:: + Column_definition_fix_attributes(Column_definition *def) const +{ + def->flags|= BLOB_FLAG; + return false; +} + +void Type_handler_geometry:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + def->srid= ((Field_geom*) field)->srid; +} + + +bool Type_handler_geometry:: + Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *def, + handler *file, + ulonglong table_flags) const +{ + def->create_length_to_internal_length_string(); + return def->prepare_blob_field(thd); +} + + +bool Type_handler_geometry:: + Column_definition_prepare_stage2(Column_definition *def, + handler *file, + ulonglong table_flags) const +{ + if (!(table_flags & HA_CAN_GEOMETRY)) + { + my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY"); + return true; + } + return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_GEOM); +} + +bool Type_handler_geometry::Key_part_spec_init_primary(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + return part->check_primary_key_for_blob(file); +} + + +bool Type_handler_geometry::Key_part_spec_init_unique(Key_part_spec *part, + const Column_definition &def, + const handler *file, + bool *hash_field_needed) const +{ + if (!part->length) + *hash_field_needed= true; + return part->check_key_for_blob(file); +} + + +bool Type_handler_geometry::Key_part_spec_init_multiple(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + return part->init_multiple_key_for_blob(file); +} + + +bool Type_handler_geometry::Key_part_spec_init_foreign(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + return part->check_foreign_key_for_blob(file); +} + + +bool Type_handler_geometry::Key_part_spec_init_spatial(Key_part_spec *part, + const Column_definition &def) + const +{ + if (part->length) + { + my_error(ER_WRONG_SUB_KEY, MYF(0)); + return true; + } + /* + 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case + Lately we'll extend this code to support more dimensions + */ + part->length= 4 * sizeof(double); + return false; +} + + +bool Type_handler_point::Key_part_spec_init_primary(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + /* + QQ: + The below assignment (here and in all other Key_part_spec_init_xxx methods) + overrides the explicitly given key part length, so in this query: + CREATE OR REPLACE TABLE t1 (a POINT, KEY(a(10))); + the key becomes KEY(a(25)). + This might be a bug. + */ + part->length= octet_length(); + return part->check_key_for_blob(file); +} + + +bool Type_handler_point::Key_part_spec_init_unique(Key_part_spec *part, + const Column_definition &def, + const handler *file, + bool *hash_field_needed) const +{ + part->length= octet_length(); + return part->check_key_for_blob(file); +} + + +bool Type_handler_point::Key_part_spec_init_multiple(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + part->length= octet_length(); + return part->check_key_for_blob(file); +} + + +bool Type_handler_point::Key_part_spec_init_foreign(Key_part_spec *part, + const Column_definition &def, + const handler *file) const +{ + part->length= octet_length(); + return part->check_key_for_blob(file); +} + + +Item * +Type_handler_point::make_constructor_item(THD *thd, List *args) const +{ + if (!args || args->elements != 2) + return NULL; + Item_args tmp(thd, *args); + return new (thd->mem_root) Item_func_point(thd, + tmp.arguments()[0], + tmp.arguments()[1]); +} + + +Item * +Type_handler_linestring::make_constructor_item(THD *thd, List *args) const +{ + return args ? new (thd->mem_root) Item_func_linestring(thd, *args) : NULL; +} + + +Item * +Type_handler_polygon::make_constructor_item(THD *thd, List *args) const +{ + return args ? new (thd->mem_root) Item_func_polygon(thd, *args) : NULL; +} + + +Item * +Type_handler_multipoint::make_constructor_item(THD *thd, List *args) const +{ + return args ? new (thd->mem_root) Item_func_multipoint(thd, *args) : NULL; +} + + +Item * +Type_handler_multilinestring::make_constructor_item(THD *thd, + List *args) const +{ + return args ? new (thd->mem_root) Item_func_multilinestring(thd, *args) : + NULL; +} + + +Item * +Type_handler_multipolygon::make_constructor_item(THD *thd, + List *args) const +{ + return args ? new (thd->mem_root) Item_func_multipolygon(thd, *args) : NULL; +} + + +Item * +Type_handler_geometrycollection::make_constructor_item(THD *thd, + List *args) const +{ + return args ? new (thd->mem_root) Item_func_geometrycollection(thd, *args) : + NULL; +} + + +uint32 Type_handler_geometry::calc_pack_length(uint32 length) const +{ + return 4 + portable_sizeof_char_ptr; +} + + +Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, name, table->s, 4, this, 0); +} + + +bool Type_handler_geometry:: + Item_hybrid_func_fix_attributes(THD *thd, + const char *func_name, + Type_handler_hybrid_field_type *handler, + Type_all_attributes *func, + Item **items, uint nitems) const +{ + DBUG_ASSERT(nitems > 0); + func->collation.set(&my_charset_bin); + func->unsigned_flag= false; + func->decimals= 0; + func->max_length= (uint32) UINT_MAX32; + func->set_maybe_null(true); + return false; +} + + +bool Type_handler_geometry:: + Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const +{ + return Item_func_or_sum_illegal_param("sum"); +} + + +bool Type_handler_geometry:: + Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const +{ + return Item_func_or_sum_illegal_param("avg"); +} + + +bool Type_handler_geometry:: + Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_func_round_fix_length_and_dec(Item_func_round *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_func_abs_fix_length_and_dec(Item_func_abs *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_func_neg_fix_length_and_dec(Item_func_neg *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + + +bool Type_handler_geometry:: + Item_func_signed_fix_length_and_dec(Item_func_signed *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const +{ + if (item->cast_charset() != &my_charset_bin) + return Item_func_or_sum_illegal_param(item); // CAST(geom AS CHAR) + item->fix_length_and_dec_str(); + return false; // CAST(geom AS BINARY) +} + + +bool Type_handler_geometry:: + Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + + +bool Type_handler_geometry:: + Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const +{ + return Item_func_or_sum_illegal_param(item); +} + + +bool Type_handler_geometry:: + Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) + const +{ + return Item_func_or_sum_illegal_param(item); + +} + + +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->setup_conversion_blob(thd); + return param->set_str(val->m_string.ptr(), val->m_string.length(), + &my_charset_bin, &my_charset_bin); +} + + +void Type_handler_geometry::Item_param_set_param_func(Item_param *param, + uchar **pos, + ulong len) const +{ + param->set_null(); // Not possible type code in the client-server protocol +} + + +Field *Type_handler_geometry:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + status_var_increment(current_thd->status_var.feature_gis); + return new (mem_root) + Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), this, attr->srid); +} + + +void Type_handler_geometry:: + Column_definition_attributes_frm_pack(const Column_definition_attributes *def, + uchar *buff) const +{ + def->frm_pack_basic(buff); + buff[11]= 0; + buff[14]= (uchar) geometry_type(); +} + + +bool Type_handler_geometry:: + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) + const +{ + uint gis_opt_read, gis_length, gis_decimals; + Field_geom::storage_type st_type; + attr->frm_unpack_basic(buffer); + gis_opt_read= gis_field_options_read(gis_options->str, + gis_options->length, + &st_type, &gis_length, + &gis_decimals, &attr->srid); + gis_options->str+= gis_opt_read; + gis_options->length-= gis_opt_read; + return false; +} + + +uint32 +Type_handler_geometry::max_display_length_for_field(const Conv_source &src) + const +{ + return (uint32) my_set_bits(4 * 8); +} + + +enum_conv_type +Field_geom::rpl_conv_type_from(const Conv_source &source, + const Relay_log_info *rli, + const Conv_param ¶m) const +{ + return binlog_type() == source.real_field_type() ? + rpl_conv_type_from_same_data_type(source.metadata(), rli, param) : + CONV_TYPE_IMPOSSIBLE; +} + + +#endif // HAVE_SPATIAL diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h new file mode 100644 index 00000000000..896debc0e08 --- /dev/null +++ b/sql/sql_type_geom.h @@ -0,0 +1,306 @@ +#ifndef SQL_TYPE_GEOM_H_INCLUDED +#define SQL_TYPE_GEOM_H_INCLUDED +/* + Copyright (c) 2015 MariaDB Foundation + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#include "mariadb.h" +#include "sql_type.h" + +#ifdef HAVE_SPATIAL +class Type_handler_geometry: public Type_handler_string_result +{ + static const Name m_name_geometry; +public: + enum geometry_types + { + GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3, + GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6, + GEOM_GEOMETRYCOLLECTION = 7 + }; + static bool check_type_geom_or_binary(const char *opname, const Item *item); + static bool check_types_geom_or_binary(const char *opname, + Item * const *args, + uint start, uint end); + static const Type_handler_geometry *type_handler_geom_by_type(uint type); +public: + virtual ~Type_handler_geometry() {} + const Name name() const override { return m_name_geometry; } + enum_field_types field_type() const override { return MYSQL_TYPE_GEOMETRY; } + bool is_param_long_data_type() const override { return true; } + uint32 max_display_length_for_field(const Conv_source &src) const override; + uint32 calc_pack_length(uint32 length) const override; + const Type_collection *type_collection() const override; + const Type_handler *type_handler_for_comparison() const override; + virtual geometry_types geometry_type() const { return GEOM_GEOMETRY; } + const Type_handler *type_handler_frm_unpack(const uchar *buffer) + const override; + bool is_binary_compatible_geom_super_type_for(const Type_handler_geometry *th) + const + { + return geometry_type() == GEOM_GEOMETRY || + geometry_type() == th->geometry_type(); + } + bool type_can_have_key_part() const override { return true; } + bool subquery_type_allows_materialization(const Item *inner, + const Item *outer) const override + { + return false; // Materialization does not work with GEOMETRY columns + } + void Item_param_set_param_func(Item_param *param, + uchar **pos, ulong len) const override; + bool Item_param_set_from_value(THD *thd, + Item_param *param, + const Type_all_attributes *attr, + const st_value *value) const override; + Field *make_conversion_table_field(TABLE *, uint metadata, + const Field *target) const override; + void + Column_definition_attributes_frm_pack(const Column_definition_attributes *at, + uchar *buff) const override; + bool + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) const + override; + bool Column_definition_fix_attributes(Column_definition *c) const override; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const + override; + bool Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *c, + handler *file, + ulonglong table_flags) const override; + bool Column_definition_prepare_stage2(Column_definition *c, + handler *file, + ulonglong table_flags) const override; + bool Key_part_spec_init_primary(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; + bool Key_part_spec_init_unique(Key_part_spec *part, + const Column_definition &def, + const handler *file, + bool *has_key_needed) const override; + bool Key_part_spec_init_multiple(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; + bool Key_part_spec_init_foreign(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; + bool Key_part_spec_init_spatial(Key_part_spec *part, + const Column_definition &def) const override; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const override; + + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const override; + + bool can_return_int() const override { return false; } + bool can_return_decimal() const override { return false; } + bool can_return_real() const override { return false; } + bool can_return_text() const override { return false; } + bool can_return_date() const override { return false; } + bool can_return_time() const override { return false; } + bool is_traditional_type() const override { return false; } + bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; + bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override; + bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; + bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override; + bool Item_hybrid_func_fix_attributes(THD *thd, + const char *name, + Type_handler_hybrid_field_type *h, + Type_all_attributes *attr, + Item **items, uint nitems) const + override; + bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override; + bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override; + bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override; + + bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override; + bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const + override; + bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const + override; + bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const + override; + bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const + override; + bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const + override; + bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const + override; + bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const + override; + bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const + override; +}; + + +class Type_handler_point: public Type_handler_geometry +{ + static const Name m_name_point; + // Binary length of a POINT value: 4 byte SRID + 21 byte WKB POINT + static uint octet_length() { return 25; } +public: + geometry_types geometry_type() const override { return GEOM_POINT; } + const Name name() const override { return m_name_point; } + Item *make_constructor_item(THD *thd, List *args) const override; + bool Key_part_spec_init_primary(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; + bool Key_part_spec_init_unique(Key_part_spec *part, + const Column_definition &def, + const handler *file, + bool *has_key_needed) const override; + bool Key_part_spec_init_multiple(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; + bool Key_part_spec_init_foreign(Key_part_spec *part, + const Column_definition &def, + const handler *file) const override; +}; + + +class Type_handler_linestring: public Type_handler_geometry +{ + static const Name m_name_linestring; +public: + geometry_types geometry_type() const { return GEOM_LINESTRING; } + const Name name() const { return m_name_linestring; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +class Type_handler_polygon: public Type_handler_geometry +{ + static const Name m_name_polygon; +public: + geometry_types geometry_type() const { return GEOM_POLYGON; } + const Name name() const { return m_name_polygon; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +class Type_handler_multipoint: public Type_handler_geometry +{ + static const Name m_name_multipoint; +public: + geometry_types geometry_type() const { return GEOM_MULTIPOINT; } + const Name name() const { return m_name_multipoint; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +class Type_handler_multilinestring: public Type_handler_geometry +{ + static const Name m_name_multilinestring; +public: + geometry_types geometry_type() const { return GEOM_MULTILINESTRING; } + const Name name() const { return m_name_multilinestring; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +class Type_handler_multipolygon: public Type_handler_geometry +{ + static const Name m_name_multipolygon; +public: + geometry_types geometry_type() const { return GEOM_MULTIPOLYGON; } + const Name name() const { return m_name_multipolygon; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +class Type_handler_geometrycollection: public Type_handler_geometry +{ + static const Name m_name_geometrycollection; +public: + geometry_types geometry_type() const { return GEOM_GEOMETRYCOLLECTION; } + const Name name() const { return m_name_geometrycollection; } + Item *make_constructor_item(THD *thd, List *args) const override; +}; + + +extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry; +extern MYSQL_PLUGIN_IMPORT Type_handler_point type_handler_point; +extern MYSQL_PLUGIN_IMPORT Type_handler_linestring type_handler_linestring; +extern MYSQL_PLUGIN_IMPORT Type_handler_polygon type_handler_polygon; +extern MYSQL_PLUGIN_IMPORT Type_handler_multipoint type_handler_multipoint; +extern MYSQL_PLUGIN_IMPORT Type_handler_multilinestring type_handler_multilinestring; +extern MYSQL_PLUGIN_IMPORT Type_handler_multipolygon type_handler_multipolygon; +extern MYSQL_PLUGIN_IMPORT Type_handler_geometrycollection type_handler_geometrycollection; + + +class Type_collection_geometry: public Type_collection +{ + const Type_handler *aggregate_common(const Type_handler *a, + const Type_handler *b) const + { + if (a == b) + return a; + DBUG_ASSERT(dynamic_cast(a)); + DBUG_ASSERT(dynamic_cast(b)); + return &type_handler_geometry; + } + bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const; +public: + bool init(Type_handler_data *data) override; + const Type_handler *handler_by_name(const LEX_CSTRING &name) const override; + const Type_handler *aggregate_for_result(const Type_handler *a, + const Type_handler *b) + const override + { + return aggregate_common(a, b); + } + const Type_handler *aggregate_for_comparison(const Type_handler *a, + const Type_handler *b) + const override + { + return aggregate_common(a, b); + } + const Type_handler *aggregate_for_min_max(const Type_handler *a, + const Type_handler *b) + const override + { + return aggregate_common(a, b); + } + const Type_handler *aggregate_for_num_op(const Type_handler *a, + const Type_handler *b) + const override + { + return NULL; + } +}; + +extern MYSQL_PLUGIN_IMPORT Type_collection_geometry type_collection_geometry; + +#endif // HAVE_SPATIAL + +#endif // SQL_TYPE_GEOM_H_INCLUDED