diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index d8d424897fb..b65ea09aaa5 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5437,3 +5437,69 @@ DROP TABLE t1; # # End of 10.5 tests # +# +# Start of 11.5 tests +# +# +# MDEV-12668 SRID is not preserved in UNION, VIEW, MIN, MAX +# +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=0, b POINT REF_SYSTEM_ID=102); +SELECT a FROM t1 UNION SELECT b FROM t1; +ERROR HY000: Illegal parameter data types `point ref_system_id=0` and `point ref_system_id=102` for operation 'UNION' +DROP TABLE t1; +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=102); +SELECT a FROM t1 UNION SELECT b FROM t1; +ERROR HY000: Illegal parameter data types `point ref_system_id=101` and `point ref_system_id=102` for operation 'UNION' +DROP TABLE t1; +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=101); +CREATE TABLE t2 AS SELECT a, b FROM t1; +CREATE VIEW v2 AS SELECT a, b FROM t1; +CREATE TABLE t3 AS SELECT a FROM t1 UNION SELECT b FROM t1; +CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1; +CREATE TABLE t4 AS SELECT COALESCE(a,b) AS a FROM t1; +CREATE VIEW v4 AS SELECT COALESCE(a,b) AS a FROM t1; +CREATE TABLE t5 AS SELECT LEAST(a,b) AS a FROM t1; +CREATE VIEW v5 AS SELECT LEAST(a,b) AS a FROM t1; +CREATE TABLE t6 AS SELECT MIN(a) AS a FROM t1; +CREATE VIEW v6 AS SELECT MIN(a) AS a FROM t1; +CREATE TABLE t7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2; +CREATE VIEW v7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2; +CREATE TABLE t8 AS SELECT (SELECT a FROM t1) AS a; +CREATE VIEW v8 AS SELECT (SELECT a FROM t1) AS a; +CREATE TABLE t9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1))); +CREATE VIEW v9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1))); +SELECT +G_TABLE_NAME, G_GEOMETRY_COLUMN, SRID +FROM +INFORMATION_SCHEMA.GEOMETRY_COLUMNS +WHERE +F_TABLE_SCHEMA='test' +ORDER +BY G_TABLE_NAME, G_GEOMETRY_COLUMN; +G_TABLE_NAME G_GEOMETRY_COLUMN SRID +t1 a 101 +t1 b 101 +t2 a 101 +t2 b 101 +t3 a 101 +t4 a 101 +t5 a 101 +t6 a 101 +t7 a 101 +t8 a 101 +t9 (SELECT MAX(a) FROM t1) 101 +v2 a 101 +v2 b 101 +v3 a 101 +v4 a 101 +v5 a 101 +v6 a 101 +v7 a 101 +v8 a 101 +v9 (select max(`test`.`t1`.`a`) from `test`.`t1`) 101 +DROP TABLE t2,t3,t4,t5,t6,t7,t8,t9; +DROP VIEW v2,v3,v4,v5,v6,v7,v8,v9; +DROP TABLE t1; +# +# End of 11.5 tests +# diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index 659636b14d3..76f51b6d6ce 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -3441,3 +3441,64 @@ DROP TABLE t1; --echo # --echo # End of 10.5 tests --echo # + +--echo # +--echo # Start of 11.5 tests +--echo # + +--echo # +--echo # MDEV-12668 SRID is not preserved in UNION, VIEW, MIN, MAX +--echo # + +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=0, b POINT REF_SYSTEM_ID=102); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT a FROM t1 UNION SELECT b FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=102); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT a FROM t1 UNION SELECT b FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=101); + +CREATE TABLE t2 AS SELECT a, b FROM t1; +CREATE VIEW v2 AS SELECT a, b FROM t1; + +CREATE TABLE t3 AS SELECT a FROM t1 UNION SELECT b FROM t1; +CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1; + +CREATE TABLE t4 AS SELECT COALESCE(a,b) AS a FROM t1; +CREATE VIEW v4 AS SELECT COALESCE(a,b) AS a FROM t1; + +CREATE TABLE t5 AS SELECT LEAST(a,b) AS a FROM t1; +CREATE VIEW v5 AS SELECT LEAST(a,b) AS a FROM t1; + +CREATE TABLE t6 AS SELECT MIN(a) AS a FROM t1; +CREATE VIEW v6 AS SELECT MIN(a) AS a FROM t1; + +CREATE TABLE t7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2; +CREATE VIEW v7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2; + +CREATE TABLE t8 AS SELECT (SELECT a FROM t1) AS a; +CREATE VIEW v8 AS SELECT (SELECT a FROM t1) AS a; + +CREATE TABLE t9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1))); +CREATE VIEW v9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1))); + +SELECT + G_TABLE_NAME, G_GEOMETRY_COLUMN, SRID +FROM + INFORMATION_SCHEMA.GEOMETRY_COLUMNS +WHERE + F_TABLE_SCHEMA='test' +ORDER + BY G_TABLE_NAME, G_GEOMETRY_COLUMN; + +DROP TABLE t2,t3,t4,t5,t6,t7,t8,t9; +DROP VIEW v2,v3,v4,v5,v6,v7,v8,v9; +DROP TABLE t1; + +--echo # +--echo # End of 11.5 tests +--echo # diff --git a/sql/field.cc b/sql/field.cc index 5e116588921..564c7d0639e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9341,7 +9341,7 @@ int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs) /* Remove end space */ length= (uint) field_charset()->lengthsp(from, length); - uint tmp=find_type2(typelib, from, length, field_charset()); + uint tmp=find_type2(m_typelib, from, length, field_charset()); if (!tmp) { if (length < 6) // Can't be more than 99999 enums @@ -9349,7 +9349,7 @@ int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs) /* This is for reading numbers with LOAD DATA INFILE */ char *end; tmp=(uint) cs->strntoul(from,length,10,&end,&err); - if (err || end != from+length || tmp > typelib->count) + if (err || end != from + length || tmp > m_typelib->count) { tmp=0; set_warning(WARN_DATA_TRUNCATED, 1); @@ -9379,7 +9379,7 @@ int Field_enum::store(longlong nr, bool unsigned_val) { DBUG_ASSERT(marked_for_write_or_computed()); int error= 0; - if ((ulonglong) nr > typelib->count || nr == 0) + if ((ulonglong) nr > m_typelib->count || nr == 0) { set_warning(WARN_DATA_TRUNCATED, 1); if (nr != 0 || get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION) @@ -9425,7 +9425,7 @@ Binlog_type_info Field_enum::binlog_type_info() const { DBUG_ASSERT(Field_enum::type() == binlog_type()); return Binlog_type_info(Field_enum::type(), real_type() + (pack_length() << 8), - 2, charset(), (TYPELIB *)get_typelib(), NULL); + 2, charset(), m_typelib, NULL); } @@ -9433,12 +9433,12 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { uint tmp=(uint) Field_enum::val_int(); - if (!tmp || tmp > typelib->count) + if (!tmp || tmp > m_typelib->count) val_ptr->set("", 0, field_charset()); else - val_ptr->set((const char*) typelib->type_names[tmp-1], - typelib->type_lengths[tmp-1], - field_charset()); + val_ptr->set((const char*) m_typelib->type_names[tmp - 1], + m_typelib->type_lengths[tmp - 1], + field_charset()); return val_ptr; } @@ -9470,8 +9470,8 @@ void Field_enum::sql_type(String &res) const res.append(STRING_WITH_LEN("enum(")); bool flag=0; - uint *len= typelib->type_lengths; - for (const char **pos= typelib->type_names; *pos; pos++, len++) + uint *len= m_typelib->type_lengths; + for (const char **pos= m_typelib->type_names; *pos; pos++, len++) { uint dummy_errors; if (flag) @@ -9491,7 +9491,7 @@ Field *Field_enum::make_new_field(MEM_ROOT *root, TABLE *new_table, Field_enum *res= (Field_enum*) Field::make_new_field(root, new_table, keep_type); if (res) - res->typelib= copy_typelib(root, typelib); + res->m_typelib= copy_typelib(root, m_typelib); return res; } @@ -9524,7 +9524,7 @@ int Field_set::store(const char *from,size_t length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); } - ulonglong tmp= find_set(typelib, from, length, field_charset(), + ulonglong tmp= find_set(m_typelib, from, length, field_charset(), ¬_used, ¬_used2, &got_warning); if (!tmp && length && length < 22) { @@ -9552,10 +9552,10 @@ int Field_set::store(longlong nr, bool unsigned_val) int error= 0; ulonglong max_nr; - if (sizeof(ulonglong)*8 <= typelib->count) + if (sizeof(ulonglong) * 8 <= m_typelib->count) max_nr= ULONGLONG_MAX; else - max_nr= (1ULL << typelib->count) - 1; + max_nr= (1ULL << m_typelib->count) - 1; if ((ulonglong) nr > max_nr) { @@ -9577,13 +9577,13 @@ String *Field_set::val_str(String *val_buffer, val_buffer->set_charset(field_charset()); val_buffer->length(0); - while (tmp && bitnr < (uint) typelib->count) + while (tmp && bitnr < (uint) m_typelib->count) { if (tmp & 1) { if (val_buffer->length()) val_buffer->append(&field_separator, 1, &my_charset_latin1); - String str(typelib->type_names[bitnr], typelib->type_lengths[bitnr], + String str(m_typelib->type_names[bitnr], m_typelib->type_lengths[bitnr], field_charset()); val_buffer->append(str); } @@ -9603,8 +9603,8 @@ void Field_set::sql_type(String &res) const res.append(STRING_WITH_LEN("set(")); bool flag=0; - uint *len= typelib->type_lengths; - for (const char **pos= typelib->type_names; *pos; pos++, len++) + uint *len= m_typelib->type_lengths; + for (const char **pos= m_typelib->type_names; *pos; pos++, len++) { uint dummy_errors; if (flag) @@ -9621,7 +9621,7 @@ Binlog_type_info Field_set::binlog_type_info() const { DBUG_ASSERT(Field_set::type() == binlog_type()); return Binlog_type_info(Field_set::type(), real_type() - + (pack_length() << 8), 2, charset(), NULL, (TYPELIB *)get_typelib()); + + (pack_length() << 8), 2, charset(), NULL, m_typelib); } /** @@ -9668,13 +9668,13 @@ bool Field_enum::eq_def(const Field *field) const if (!Field::eq_def(field)) return FALSE; - values= ((Field_enum*) field)->typelib; + values= ((Field_enum*) field)->m_typelib; /* Definition must be strictly equal. */ - if (typelib->count != values->count) + if (m_typelib->count != values->count) return FALSE; - return compare_type_names(field_charset(), typelib, values); + return compare_type_names(field_charset(), m_typelib, values); } @@ -9689,8 +9689,6 @@ bool Field_enum::eq_def(const Field *field) const bool Field_enum::is_equal(const Column_definition &new_field) const { - const TYPELIB *values= new_field.interval; - /* The fields are compatible if they have the same flags, type, charset and have the same underlying length. @@ -9705,11 +9703,11 @@ bool Field_enum::is_equal(const Column_definition &new_field) const enumeration or set members to the end of the list of valid member values only alters table metadata and not table data. */ - if (typelib->count > values->count) + if (m_typelib->count > new_field.typelib()->count) return false; /* Check whether there are modification before the end. */ - if (! compare_type_names(field_charset(), typelib, new_field.interval)) + if (! compare_type_names(field_charset(), m_typelib, new_field.typelib())) return false; return true; @@ -10405,9 +10403,10 @@ bool Column_definition::create_interval_from_interval_list(MEM_ROOT *mem_root, bool reuse_interval_list_values) { DBUG_ENTER("Column_definition::create_interval_from_interval_list"); - DBUG_ASSERT(!interval); + DBUG_ASSERT(!typelib()); TYPELIB *tmpint; - if (!(interval= tmpint= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)))) + if (!set_typelib(tmpint= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB))). + typelib()) DBUG_RETURN(true); // EOM List_iterator it(interval_list); @@ -10476,7 +10475,8 @@ bool Column_definition::create_interval_from_interval_list(MEM_ROOT *mem_root, interval_list.empty(); // Don't need interval_list anymore DBUG_RETURN(false); err: - interval= NULL; // Avoid having both non-empty interval_list and interval + // Avoid having both non-empty interval_list and the typelib attribute + set_typelib(NULL); DBUG_RETURN(true); } @@ -10504,7 +10504,7 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root, as the parser requires at least one element, so for a ENUM or SET field it should never happen that both internal_list.elements and interval are 0. */ - DBUG_ASSERT((interval == NULL) == (interval_list.elements > 0)); + DBUG_ASSERT((typelib() == NULL) == (interval_list.elements > 0)); /* Create typelib from interval_list, and if necessary @@ -10527,8 +10527,8 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root, as the original field can be freed before the end of the life cycle of "this". */ - DBUG_ASSERT(interval); - if (!(interval= copy_typelib(mem_root, interval))) + DBUG_ASSERT(typelib()); + if (!set_typelib(copy_typelib(mem_root, typelib())).typelib()) DBUG_RETURN(true); } prepare_interval_field_calc_length(); @@ -10886,7 +10886,7 @@ Field *Column_definition_attributes::make_field(TABLE_SHARE *share, { DBUG_ASSERT(length <= UINT_MAX32); DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", - handler->name().ptr(), (uint) length, interval, + handler->name().ptr(), (uint) length, typelib(), FLAGSTR(pack_flag, FIELDFLAG_BINARY), FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), FLAGSTR(pack_flag, FIELDFLAG_NUMBER), @@ -10915,9 +10915,7 @@ bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) Column_definition_attributes::Column_definition_attributes(const Field *field) :length(field->character_octet_length() / field->charset()->mbmaxlen), - interval(NULL), charset(field->charset()), // May be NULL ptr - srid(0), pack_flag(0), decimals(field->decimals()), unireg_check(field->unireg_check) @@ -10926,10 +10924,9 @@ Column_definition_attributes::Column_definition_attributes(const Field *field) Column_definition_attributes:: Column_definition_attributes(const Type_all_attributes &attr) - :length(attr.max_length), - interval(attr.get_typelib()), + :Type_extra_attributes(attr.type_extra_attributes()), + length(attr.max_length), charset(attr.collation.collation), - srid(0), pack_flag(attr.unsigned_flag ? 0 : FIELDFLAG_DECIMAL), decimals(attr.decimals), unireg_check(Field::NONE) @@ -10942,7 +10939,6 @@ Column_definition::Column_definition(THD *thd, Field *old_field, Field *orig_field) :Column_definition_attributes(old_field) { - srid= 0; on_update= NULL; field_name= old_field->field_name; flags= old_field->flags; @@ -11034,6 +11030,7 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, const handler *file) { set_handler(dup_field->type_handler()); + Type_extra_attributes::operator=(*dup_field); default_value= dup_field->default_value; DBUG_ASSERT(dup_field->charset); // Set by prepare_stage1() charset= dup_field->charset; @@ -11042,7 +11039,6 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, decimals= dup_field->decimals; unireg_check= dup_field->unireg_check; flags= dup_field->flags; - interval= dup_field->interval; vcol_info= dup_field->vcol_info; invisible= dup_field->invisible; check_constraint= dup_field->check_constraint; diff --git a/sql/field.h b/sql/field.h index 1147e1a7f66..5331500cc52 100644 --- a/sql/field.h +++ b/sql/field.h @@ -662,8 +662,8 @@ public: Retrieve the field metadata for fields. */ CHARSET_INFO *m_cs; // NULL if not relevant - TYPELIB *m_enum_typelib; // NULL if not relevant - TYPELIB *m_set_typelib; // NULL if not relevant + const TYPELIB *m_enum_typelib; // NULL if not relevant + const TYPELIB *m_set_typelib; // NULL if not relevant binlog_sign_t m_signedness; uint16 m_metadata; uint8 m_metadata_size; @@ -708,7 +708,7 @@ public: Binlog_type_info(uchar type_code, uint16 metadata, uint8 metadata_size, CHARSET_INFO *cs, - TYPELIB *t_enum, TYPELIB *t_set) + const TYPELIB *t_enum, const TYPELIB *t_set) :m_cs(cs), m_enum_typelib(t_enum), m_set_typelib(t_set), @@ -1661,7 +1661,10 @@ public: virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); virtual longlong val_datetime_packed(THD *thd); virtual longlong val_time_packed(THD *thd); - virtual const TYPELIB *get_typelib() const { return NULL; } + virtual const Type_extra_attributes type_extra_attributes() const + { + return Type_extra_attributes(); + } virtual CHARSET_INFO *charset() const= 0; /* returns TRUE if the new charset differs. */ virtual void change_charset(const DTCollation &new_cs) {} @@ -4778,7 +4781,9 @@ private: }; -class Field_enum :public Field_str { +class Field_enum :public Field_str, + public Type_typelib_attributes +{ static void do_field_enum(const Copy_field *copy_field); longlong val_int(const uchar *) const; Data_type_compatibility can_optimize_range_or_keypart_ref( @@ -4787,7 +4792,6 @@ class Field_enum :public Field_str { protected: uint packlength; public: - const TYPELIB *typelib; Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, @@ -4796,7 +4800,8 @@ public: const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, collation), - packlength(packlength_arg),typelib(typelib_arg) + Type_typelib_attributes(typelib_arg), + packlength(packlength_arg) { flags|=ENUM_FLAG; } @@ -4869,8 +4874,10 @@ public: /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset() const override { return &my_charset_bin; } decimal_digits_t decimals() const override { return 0; } - const TYPELIB *get_typelib() const override { return typelib; } - + const Type_extra_attributes type_extra_attributes() const override + { + return Type_extra_attributes(m_typelib); + } uchar *pack(uchar *to, const uchar *from, uint max_length) override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; @@ -5198,7 +5205,7 @@ public: extern const LEX_CSTRING null_clex_str; -class Column_definition_attributes +class Column_definition_attributes: public Type_extra_attributes { public: /* @@ -5206,17 +5213,13 @@ public: max number of characters. */ ulonglong length; - const TYPELIB *interval; CHARSET_INFO *charset; - uint32 srid; uint32 pack_flag; decimal_digits_t decimals; Field::utype unireg_check; Column_definition_attributes() :length(0), - interval(NULL), charset(&my_charset_bin), - srid(0), pack_flag(0), decimals(0), unireg_check(Field::NONE) @@ -5287,7 +5290,7 @@ class Column_definition: public Sql_alloc, const char **pos; uint *len; *max_length= *tot_length= 0; - for (pos= interval->type_names, len= interval->type_lengths; + for (pos= typelib()->type_names, len= typelib()->type_lengths; *pos ; pos++, len++) { size_t length= charset->numchars(*pos, *pos + *len); @@ -5412,7 +5415,7 @@ public: if (real_field_type() == MYSQL_TYPE_SET) { calculate_interval_lengths(&dummy, &field_length); - length= field_length + (interval->count - 1); + length= field_length + (typelib()->count - 1); } else /* MYSQL_TYPE_ENUM */ { @@ -5516,15 +5519,14 @@ public: void set_type(const Column_definition &other) { set_handler(other.type_handler()); + Type_extra_attributes::operator=(other); length= other.length; char_length= other.char_length; decimals= other.decimals; flags= other.flags; pack_length= other.pack_length; unireg_check= other.unireg_check; - interval= other.interval; charset= other.charset; - srid= other.srid; pack_flag= other.pack_flag; } diff --git a/sql/item.h b/sql/item.h index 109882ff920..b5f1413b75e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1328,7 +1328,14 @@ public: { return type_handler()->max_display_length(this); } - const TYPELIB *get_typelib() const override { return NULL; } + const Type_extra_attributes type_extra_attributes() const override + { + return Type_extra_attributes(); + } + Type_extra_attributes *type_extra_attributes_addr() override + { + return nullptr; + } /* optimized setting of maybe_null without jumps. Minimizes code size */ inline void set_maybe_null(bool maybe_null_arg) { @@ -1366,11 +1373,6 @@ public: bool is_top_level_item() const { return (bool) (base_flags & item_base_t::AT_TOP_LEVEL); } - void set_typelib(const TYPELIB *typelib) override - { - // Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet. - DBUG_ASSERT(0); - } Item_cache* get_cache(THD *thd) const { return type_handler()->Item_get_cache(thd, this); @@ -3696,7 +3698,10 @@ public: Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; - const TYPELIB *get_typelib() const override { return field->get_typelib(); } + const Type_extra_attributes type_extra_attributes() const override + { + return field->type_extra_attributes(); + } enum_monotonicity_info get_monotonicity_info() const override { return MONOTONIC_STRICT_INCREASING; @@ -5731,9 +5736,9 @@ public: { return ref ? (*ref)->real_item() : this; } - const TYPELIB *get_typelib() const override + const Type_extra_attributes type_extra_attributes() const override { - return ref ? (*ref)->get_typelib() : NULL; + return ref ? (*ref)->type_extra_attributes() : Type_extra_attributes(); } bool walk(Item_processor processor, bool walk_subquery, void *arg) override @@ -7154,6 +7159,12 @@ public: const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } + const Type_extra_attributes type_extra_attributes() const override + { + DBUG_ASSERT(fixed()); + return example ? example->type_extra_attributes() : + Type_extra_attributes(); + } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override { @@ -7677,15 +7688,17 @@ public: Item_type_holder do not need cleanup() because its time of live limited by single SP/PS execution. */ -class Item_type_holder: public Item, public Type_handler_hybrid_field_type +class Item_type_holder: public Item, + public Type_handler_hybrid_field_type, + public Type_extra_attributes { -protected: - const TYPELIB *enum_set_typelib; public: Item_type_holder(THD *thd, Item *item, const Type_handler *handler, - const Type_all_attributes *attr, bool maybe_null_arg) - :Item(thd), Type_handler_hybrid_field_type(handler), - enum_set_typelib(attr->get_typelib()) + const Type_all_attributes *attr, + bool maybe_null_arg) + :Item(thd), + Type_handler_hybrid_field_type(handler), + Type_extra_attributes(attr->type_extra_attributes()) { name= item->name; Type_std_attributes::set(*attr); @@ -7705,7 +7718,14 @@ public: } Type type() const override { return TYPE_HOLDER; } - const TYPELIB *get_typelib() const override { return enum_set_typelib; } + Type_extra_attributes *type_extra_attributes_addr() override + { + return this; + } + const Type_extra_attributes type_extra_attributes() const override + { + return *this; + } /* When handling a query like this: VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin); diff --git a/sql/item_func.cc b/sql/item_func.cc index 38ca845393d..3c6c059bc3b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3295,8 +3295,8 @@ bool Item_func_find_in_set::fix_length_and_dec(THD *thd) { // find is not NULL pointer so args[0] is not a null-value DBUG_ASSERT(!args[0]->null_value); - enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(), - find->length(), 0); + enum_value= find_type(((Field_enum*) field)->typelib(), find->ptr(), + find->length(), 0); enum_bit=0; if (enum_value) enum_bit= 1ULL << (enum_value-1); diff --git a/sql/item_func.h b/sql/item_func.h index 6e69df3fd8b..9f71bee2bd2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -497,7 +497,8 @@ public: Functions whose returned field type is determined at fix_fields() time. */ class Item_hybrid_func: public Item_func, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Type_extra_attributes { protected: bool fix_attributes(Item **item, uint nitems); @@ -512,6 +513,14 @@ public: :Item_func(thd, item), Type_handler_hybrid_field_type(item) { } const Type_handler *type_handler() const override { return Type_handler_hybrid_field_type::type_handler(); } + Type_extra_attributes *type_extra_attributes_addr() override + { + return this; + } + const Type_extra_attributes type_extra_attributes() const override + { + return *this; + } void fix_length_and_dec_long_or_longlong(uint char_length, bool unsigned_arg) { collation= DTCollation_numeric(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 308bcb6e1ae..52e9349c932 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -4037,6 +4037,8 @@ bool subselect_single_select_engine::fix_length_and_dec(Item_cache **row) if (set_row(select_lex->item_list, row)) return TRUE; item->collation.set(row[0]->collation); + if (Type_extra_attributes *eattr= item->type_extra_attributes_addr()) + eattr[0]= row[0]->type_extra_attributes(); if (cols() != 1) maybe_null= 0; return FALSE; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index f838c0d4c8f..68ecc01d49b 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -294,7 +294,8 @@ public: /* single value subselect */ class Item_cache; -class Item_singlerow_subselect :public Item_subselect +class Item_singlerow_subselect :public Item_subselect, + public Type_extra_attributes { protected: Item_cache *value, **row; @@ -319,6 +320,14 @@ public: bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; const Type_handler *type_handler() const override; bool fix_length_and_dec() override; + Type_extra_attributes *type_extra_attributes_addr() override + { + return this; + } + const Type_extra_attributes type_extra_attributes() const override + { + return *this; + } uint cols() const override; Item* element_index(uint i) override diff --git a/sql/item_sum.h b/sql/item_sum.h index 7308734070d..146358db8fd 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1172,7 +1172,10 @@ public: { return get_arg(0)->real_type_handler(); } - const TYPELIB *get_typelib() const override { return args[0]->get_typelib(); } + const Type_extra_attributes type_extra_attributes() const override + { + return args[0]->type_extra_attributes(); + } void update_field() override; void min_max_update_str_field(); void min_max_update_real_field(); diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 8ad49247423..3691086bf69 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -6248,7 +6248,7 @@ bool Table_map_log_event::init_column_name_field() bool Table_map_log_event::init_set_str_value_field() { StringBuffer<1024> buf; - TYPELIB *typelib; + const TYPELIB *typelib; /* SET string values are stored in the same format: @@ -6278,7 +6278,7 @@ bool Table_map_log_event::init_set_str_value_field() bool Table_map_log_event::init_enum_str_value_field() { StringBuffer<1024> buf; - TYPELIB *typelib; + const TYPELIB *typelib; /* ENUM is same to SET columns, see comment in init_set_str_value_field */ for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7fb4fa1d476..f4ef77c4110 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -863,7 +863,7 @@ class Grant_table_base { Field *field= m_table->field[end_priv_columns]; if (field->real_type() == MYSQL_TYPE_ENUM && - static_cast(field)->typelib->count == 2) + static_cast(field)->typelib()->count == 2) { if (!start_priv_columns) start_priv_columns= end_priv_columns; @@ -3052,7 +3052,7 @@ static privilege_t get_access(TABLE *form, uint fieldnr, uint *next_field) for (pos=form->field+fieldnr, bit=1; *pos && (*pos)->real_type() == MYSQL_TYPE_ENUM && - ((Field_enum*) (*pos))->typelib->count == 2 ; + ((Field_enum*) (*pos))->typelib()->count == 2 ; pos++, fieldnr++, bit<<=1) { if (get_YN_as_bool(*pos)) diff --git a/sql/sql_class.h b/sql/sql_class.h index ee6547a9d8e..177de078ac7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -8197,20 +8197,22 @@ public: class Type_holder: public Sql_alloc, public Item_args, public Type_handler_hybrid_field_type, - public Type_all_attributes + public Type_all_attributes, + public Type_extra_attributes { - const TYPELIB *m_typelib; bool m_maybe_null; public: Type_holder() - :m_typelib(NULL), - m_maybe_null(false) + :m_maybe_null(false) { } - void set_type_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; } + void set_type_maybe_null(bool maybe_null_arg) override + { + m_maybe_null= maybe_null_arg; + } bool get_maybe_null() const { return m_maybe_null; } - decimal_digits_t decimal_precision() const + decimal_digits_t decimal_precision() const override { /* Type_holder is not used directly to create fields, so @@ -8222,13 +8224,13 @@ public: DBUG_ASSERT(0); return 0; } - void set_typelib(const TYPELIB *typelib) + Type_extra_attributes *type_extra_attributes_addr() override { - m_typelib= typelib; + return this; } - const TYPELIB *get_typelib() const + const Type_extra_attributes type_extra_attributes() const override { - return m_typelib; + return *this; } bool aggregate_attributes(THD *thd) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9d48a895214..dec9e45ae83 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2269,7 +2269,7 @@ bool Column_definition::prepare_stage2_typelib(const char *type_name, pack_flag= pack_length_to_packflag(pack_length) | field_flags; if (charset->state & MY_CS_BINSORT) pack_flag|= FIELDFLAG_BINARY; - return check_duplicates_in_interval(type_name, field_name.str, interval, + return check_duplicates_in_interval(type_name, field_name.str, typelib(), charset, dup_val_count); } @@ -2537,13 +2537,13 @@ bool Column_definition::prepare_stage1_check_typelib_default() { char *not_used; uint not_used2; - find_set(interval, def->ptr(), def->length(), + find_set(typelib(), def->ptr(), def->length(), charset, ¬_used, ¬_used2, ¬_found); } else /* MYSQL_TYPE_ENUM */ { def->length(charset->lengthsp(def->ptr(), def->length())); - not_found= !find_type2(interval, def->ptr(), def->length(), charset); + not_found= !find_type2(typelib(), def->ptr(), def->length(), charset); } } if (not_found) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 76fb908cdac..0bf6c406739 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2666,7 +2666,7 @@ Field *Type_handler_enum::make_conversion_table_field(MEM_ROOT *root, Field_enum(NULL, target->field_length, (uchar *) "", 1, Field::NONE, &empty_clex_str, metadata & 0x00ff/*pack_length()*/, - ((const Field_enum*) target)->typelib, target->charset()); + ((const Field_enum*) target)->typelib(), target->charset()); } @@ -2682,7 +2682,7 @@ Field *Type_handler_set::make_conversion_table_field(MEM_ROOT *root, Field_set(NULL, target->field_length, (uchar *) "", 1, Field::NONE, &empty_clex_str, metadata & 0x00ff/*pack_length()*/, - ((const Field_enum*) target)->typelib, target->charset()); + ((const Field_enum*) target)->typelib(), target->charset()); } @@ -2977,7 +2977,8 @@ void Type_handler_typelib:: const Field *field) const { DBUG_ASSERT(def->flags & (ENUM_FLAG | SET_FLAG)); - def->interval= field->get_typelib(); + const Field_enum *field_enum= static_cast(field); + field_enum->Type_typelib_attributes::store(def); } @@ -3336,7 +3337,7 @@ bool Type_handler_set:: if (def->prepare_stage2_typelib("SET", FIELDFLAG_BITFIELD, &dup_count)) return true; /* Check that count of unique members is not more then 64 */ - if (def->interval->count - dup_count > sizeof(longlong)*8) + if (def->typelib()->count - dup_count > sizeof(longlong)*8) { my_error(ER_TOO_BIG_SET, MYF(0), def->field_name.str); return true; @@ -3549,14 +3550,14 @@ Type_handler_string_result::calc_key_length(const Column_definition &def) const uint Type_handler_enum::calc_key_length(const Column_definition &def) const { - DBUG_ASSERT(def.interval); - return get_enum_pack_length(def.interval->count); + DBUG_ASSERT(def.typelib()); + return get_enum_pack_length(def.typelib()->count); } uint Type_handler_set::calc_key_length(const Column_definition &def) const { - DBUG_ASSERT(def.interval); - return get_set_pack_length(def.interval->count); + DBUG_ASSERT(def.typelib()); + return get_set_pack_length(def.typelib()->count); } uint Type_handler_blob_common::calc_key_length(const Column_definition &def) const @@ -3931,13 +3932,14 @@ Field *Type_handler_enum::make_table_field(MEM_ROOT *root, const Type_all_attributes &attr, TABLE_SHARE *share) const { - const TYPELIB *typelib= attr.get_typelib(); - DBUG_ASSERT(typelib); + const Type_typelib_attributes typelib_attr(attr.type_extra_attributes()); + DBUG_ASSERT(typelib_attr.typelib()); return new (root) Field_enum(addr.ptr(), attr.max_length, addr.null_ptr(), addr.null_bit(), Field::NONE, name, - get_enum_pack_length(typelib->count), typelib, + get_enum_pack_length(typelib_attr.typelib()->count), + typelib_attr.typelib(), attr.collation); } @@ -3949,13 +3951,14 @@ Field *Type_handler_set::make_table_field(MEM_ROOT *root, TABLE_SHARE *share) const { - const TYPELIB *typelib= attr.get_typelib(); - DBUG_ASSERT(typelib); + const Type_typelib_attributes typelib_attr(attr.type_extra_attributes()); + DBUG_ASSERT(typelib_attr.typelib()); return new (root) Field_set(addr.ptr(), attr.max_length, addr.null_ptr(), addr.null_bit(), Field::NONE, name, - get_enum_pack_length(typelib->count), typelib, + get_enum_pack_length(typelib_attr.typelib()->count), + typelib_attr.typelib(), attr.collation); } @@ -4694,8 +4697,8 @@ bool Type_handler_typelib:: const TYPELIB *typelib= NULL; for (uint i= 0; i < nitems; i++) { - const TYPELIB *typelib2; - if ((typelib2= items[i]->get_typelib())) + const Type_extra_attributes eattr2= items[i]->type_extra_attributes(); + if (eattr2.typelib()) { if (typelib) { @@ -4707,11 +4710,13 @@ bool Type_handler_typelib:: handler->set_handler(&type_handler_varchar); return func->aggregate_attributes_string(func_name, items, nitems); } - typelib= typelib2; + typelib= eattr2.typelib(); } } DBUG_ASSERT(typelib); // There must be at least one typelib - func->set_typelib(typelib); + Type_extra_attributes *eattr_addr= func->type_extra_attributes_addr(); + if (eattr_addr) + eattr_addr->set_typelib(typelib); return func->aggregate_attributes_string(func_name, items, nitems); } @@ -8536,7 +8541,7 @@ Field *Type_handler_enum:: return new (mem_root) Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, attr->pack_flag_to_pack_length(), - attr->interval, attr->charset); + attr->typelib(), attr->charset); } @@ -8550,7 +8555,7 @@ Field *Type_handler_set:: return new (mem_root) Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, attr->pack_flag_to_pack_length(), - attr->interval, attr->charset); + attr->typelib(), attr->charset); } diff --git a/sql/sql_type.h b/sql/sql_type.h index 45e94c0dbd6..ba5c3746424 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3402,6 +3402,98 @@ public: }; +/* + A container for very specific data type attributes. + For now it prodives space for: + - one const pointer attributes + - one unt32 attribute +*/ +class Type_extra_attributes +{ + const void *m_attr_const_void_ptr[1]; + uint32 m_attr_uint32[1]; +public: + Type_extra_attributes() + :m_attr_const_void_ptr{0}, + m_attr_uint32{0} + { } + Type_extra_attributes(const void *const_void_ptr) + :m_attr_const_void_ptr{const_void_ptr}, + m_attr_uint32{0} + { } + /* + Generic const pointer attributes. + The ENUM and SET data types store TYPELIB information here. + */ + Type_extra_attributes & set_attr_const_void_ptr(uint i, const void *value) + { + m_attr_const_void_ptr[i]= value; + return *this; + } + const void *get_attr_const_void_ptr(uint i) const + { + return m_attr_const_void_ptr[i]; + } + /* + Generic uint32 attributes. + The GEOMETRY data type stores SRID here. + */ + Type_extra_attributes & set_attr_uint32(uint i, uint32 value) + { + m_attr_uint32[i]= value; + return *this; + } + uint32 get_attr_uint32(uint i) const + { + return m_attr_uint32[i]; + } + /* + Helper methods for TYPELIB attributes. + They are mostly needed to simplify the code + in Column_definition_attributes and Column_definition methods. + Eventually we should move this code into Type_typelib_attributes + and remove these methods. + */ + Type_extra_attributes & set_typelib(const TYPELIB *typelib) + { + return set_attr_const_void_ptr(0, typelib); + } + const TYPELIB *typelib() const + { + return (const TYPELIB*) get_attr_const_void_ptr(0); + } +}; + + +class Type_typelib_attributes +{ +protected: + const TYPELIB *m_typelib; +public: + Type_typelib_attributes() + :m_typelib(nullptr) + { } + Type_typelib_attributes(const TYPELIB *typelib) + :m_typelib(typelib) + { } + Type_typelib_attributes(const Type_extra_attributes &eattr) + :m_typelib((const TYPELIB *) eattr.get_attr_const_void_ptr(0)) + { } + void store(Type_extra_attributes *to) const + { + to->set_attr_const_void_ptr(0, m_typelib); + } + const TYPELIB *typelib() const + { + return m_typelib; + } + void set_typelib(const TYPELIB *typelib) + { + m_typelib= typelib; + } +}; + + class Type_all_attributes: public Type_std_attributes { public: @@ -3411,8 +3503,8 @@ public: virtual void set_type_maybe_null(bool maybe_null_arg)= 0; // Returns total number of decimal digits virtual decimal_digits_t decimal_precision() const= 0; - virtual const TYPELIB *get_typelib() const= 0; - virtual void set_typelib(const TYPELIB *typelib)= 0; + virtual Type_extra_attributes *type_extra_attributes_addr() = 0; + virtual const Type_extra_attributes type_extra_attributes() const= 0; }; diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc index b026b5e9479..4f1d1f8c79d 100644 --- a/sql/sql_type_geom.cc +++ b/sql/sql_type_geom.cc @@ -22,6 +22,24 @@ #include "sql_type_geom.h" #include "item_geofunc.h" + +class GeomTypeStr: public BinaryStringBuffer<64> +{ +public: + GeomTypeStr(const Type_handler &th, const Type_geom_attributes &gattr) + { + append_char('`'); + append(th.name().lex_cstring()); + append_char(' '); + append(STRING_WITH_LEN("ref_system_id=")); + append_ulonglong(gattr.get_srid()); + append_char('`'); + DBUG_ASSERT(str_length < Alloced_length); + Ptr[str_length]= '\0'; + } +}; + + Named_type_handler type_handler_geometry("geometry"); Named_type_handler type_handler_point("point"); Named_type_handler type_handler_linestring("linestring"); @@ -256,7 +274,7 @@ Field *Type_handler_geometry::make_conversion_table_field(MEM_ROOT *root, const Field_geom *fg= static_cast(target); return new (root) Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, - table->s, 4, fg->type_handler_geom(), fg->srid); + table->s, 4, fg->type_handler_geom(), *fg); } @@ -272,7 +290,8 @@ void Type_handler_geometry:: Column_definition *def, const Field *field) const { - def->srid= ((Field_geom*) field)->srid; + DBUG_ASSERT(dynamic_cast(field)); + static_cast(field)->Type_geom_attributes::store(def); } @@ -486,13 +505,14 @@ Field *Type_handler_geometry::make_table_field(MEM_ROOT *root, { return new (root) Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(), - Field::NONE, name, share, 4, this, 0); + Field::NONE, name, share, 4, this, + Type_geom_attributes(attr.type_extra_attributes())); } bool Type_handler_geometry:: Item_hybrid_func_fix_attributes(THD *thd, - const LEX_CSTRING &func_name, + const LEX_CSTRING &op_name, Type_handler_hybrid_field_type *handler, Type_all_attributes *func, Item **items, uint nitems) const @@ -503,6 +523,24 @@ bool Type_handler_geometry:: func->decimals= 0; func->max_length= (uint32) UINT_MAX32; func->set_type_maybe_null(true); + Type_extra_attributes *func_eattr= func->type_extra_attributes_addr(); + if (func_eattr && nitems > 0) + { + Type_geom_attributes gattr(items[0]->type_extra_attributes()); + for (uint32 i= 1; i < nitems; i++) + { + const Type_geom_attributes gattr1(items[i]->type_extra_attributes()); + if (gattr.join(gattr1)) + { + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), + GeomTypeStr(*items[i-1]->type_handler(), gattr).ptr(), + GeomTypeStr(*items[i]->type_handler(), gattr1).ptr(), + op_name.str); + return true; + } + } + gattr.store(func_eattr); + } return false; } @@ -660,7 +698,8 @@ Field *Type_handler_geometry:: return new (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); + attr->pack_flag_to_pack_length(), this, + Type_geom_attributes(*attr)); } @@ -708,7 +747,7 @@ Type_handler_geometry:: cbuf[5]= (uchar) def.decimals; cbuf[6]= FIELDGEOM_SRID; - int4store(cbuf + 7, ((uint32) def.srid)); + int4store(cbuf + 7, Type_geom_attributes(def).get_srid()); cbuf[11]= FIELDGEOM_END; } @@ -775,11 +814,13 @@ bool Type_handler_geometry:: { uint gis_opt_read, gis_length, gis_decimals; Field_geom::storage_type st_type; + uint32 srid= 0; 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_decimals, &srid); + Type_geom_attributes(srid).store(attr); gis_options->str+= gis_opt_read; gis_options->length-= gis_opt_read; return false; diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index 14d3d062ef9..8f1f3f40d97 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -24,6 +24,40 @@ #include "mariadb.h" #include "sql_type.h" + +class Type_geom_attributes +{ +protected: + uint32 m_srid; +public: + Type_geom_attributes() + :m_srid(0) + { } + explicit Type_geom_attributes(const Type_extra_attributes &eattr) + :m_srid(eattr.get_attr_uint32(0)) + { } + explicit Type_geom_attributes(uint32 srid) + :m_srid(srid) + { } + void store(Type_extra_attributes *to) const + { + to->set_attr_uint32(0, m_srid); + } + void set_srid(uint32 srid) + { + m_srid= srid; + } + uint32 get_srid() const + { + return m_srid; + } + bool join(const Type_geom_attributes &rhs) + { + return m_srid != rhs.m_srid; + } +}; + + #ifdef HAVE_SPATIAL class Type_handler_geometry: public Type_handler_string_result { @@ -326,11 +360,11 @@ Type_collection_geometry_handler_by_name(const LEX_CSTRING &name); #include "field.h" -class Field_geom :public Field_blob +class Field_geom :public Field_blob, + public Type_geom_attributes { 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; @@ -339,11 +373,12 @@ public: 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) + const Type_geom_attributes &geom_attr) :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, blob_pack_length, &my_charset_bin), + Type_geom_attributes(geom_attr), 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 override; @@ -363,6 +398,12 @@ public: { m_type_handler= th; } + const Type_extra_attributes type_extra_attributes() const override + { + Type_extra_attributes eattr; + Type_geom_attributes::store(&eattr); + return eattr; + } enum_field_types type() const override { return MYSQL_TYPE_GEOMETRY; @@ -428,7 +469,6 @@ public: bool load_data_set_null(THD *thd) override; bool load_data_set_no_data(THD *thd, bool fixed_format) override; - uint get_srid() const { return srid; } void print_key_value(String *out, uint32 length) override { out->append(STRING_WITH_LEN("unprintable_geometry_value")); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9b8c1a1f268..7a96e93b17d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6494,11 +6494,11 @@ real_type: srid_option: /* empty */ - { Lex->last_field->srid= 0; } + { Lex->last_field->set_attr_uint32(0, 0); } | REF_SYSTEM_ID_SYM '=' NUM { - Lex->last_field->srid=atoi($3.str); + Lex->last_field->set_attr_uint32(0, (uint32) atoi($3.str)); } ; diff --git a/sql/table.cc b/sql/table.cc index 36621ee0b38..2d3dd601cf5 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2734,7 +2734,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, /* Convert pre-10.2.2 timestamps to use Field::default_value */ name.str= fieldnames.type_names[i]; name.length= strlen(name.str); - attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL; + attr.set_typelib(interval_nr ? share->intervals + interval_nr - 1 : NULL); Record_addr addr(record + recpos, null_pos, null_bit_pos); *field_ptr= reg_field= attr.make_field(share, &share->mem_root, &addr, handler, &name, flags); @@ -10573,7 +10573,7 @@ bool TR_table::check(bool error) } Field_enum *iso_level= static_cast(table->field[FLD_ISO_LEVEL]); - const st_typelib *typelib= iso_level->typelib; + const st_typelib *typelib= iso_level->typelib(); if (typelib->count != 4) goto wrong_enum; diff --git a/sql/unireg.cc b/sql/unireg.cc index eab107b3f21..59c2b5f0d44 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -644,7 +644,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, { if (field->save_interval) { - field->interval= field->save_interval; + field->set_typelib(field->save_interval); field->save_interval= 0; } } @@ -887,7 +887,7 @@ static bool pack_header(THD *thd, uchar *forminfo, n_length+= field->field_name.length + 1; field->interval_id=0; field->save_interval= 0; - if (field->interval) + if (field->typelib()) { uint old_int_count=int_count; @@ -902,9 +902,9 @@ static bool pack_header(THD *thd, uchar *forminfo, filled with default values it is saved in save_interval The HEX representation is created from this copy. */ - uint count= field->interval->count; - field->save_interval= field->interval; - field->interval= tmpint= (TYPELIB*) thd->alloc(sizeof(TYPELIB)); + uint count= field->typelib()->count; + field->save_interval= field->typelib(); + field->set_typelib(tmpint= (TYPELIB*) thd->alloc(sizeof(TYPELIB))); *tmpint= *field->save_interval; tmpint->type_names= (const char **) thd->alloc(sizeof(char*) * @@ -913,7 +913,7 @@ static bool pack_header(THD *thd, uchar *forminfo, tmpint->type_names[count]= 0; tmpint->type_lengths[count]= 0; - for (uint pos= 0; pos < field->interval->count; pos++) + for (uint pos= 0; pos < field->typelib()->count; pos++) { char *dst; const char *src= field->save_interval->type_names[pos]; @@ -929,8 +929,8 @@ static bool pack_header(THD *thd, uchar *forminfo, field->interval_id=get_interval_id(&int_count,create_fields,field); if (old_int_count != int_count) { - int_length+= typelib_values_packed_length(field->interval); - int_parts+= field->interval->count + 1; + int_length+= typelib_values_packed_length(field->typelib()); + int_parts+= field->typelib()->count + 1; } } if (f_maybe_null(field->pack_flag)) @@ -984,7 +984,7 @@ static uint get_interval_id(uint *int_count,List &create_fields, { List_iterator it(create_fields); Create_field *field; - const TYPELIB *interval= last_field->interval; + const TYPELIB *interval= last_field->typelib(); while ((field=it++) != last_field) { @@ -996,11 +996,11 @@ static uint get_interval_id(uint *int_count,List &create_fields, - mbminlen>1 are written to FRM in hex-encoded format */ if (field->interval_id && - field->interval->count == interval->count && + field->typelib()->count == interval->count && field->charset->mbminlen == last_field->charset->mbminlen) { const char **a,**b; - for (a=field->interval->type_names, b=interval->type_names ; + for (a= field->typelib()->type_names, b= interval->type_names ; *a && !strcmp(*a,*b); a++,b++) ; @@ -1028,7 +1028,7 @@ static size_t packed_fields_length(List &create_fields) { int_count= field->interval_id; length++; - length+= typelib_values_packed_length(field->interval); + length+= typelib_values_packed_length(field->typelib()); length++; } @@ -1096,8 +1096,8 @@ static bool pack_fields(uchar **buff_arg, List &create_fields, bzero(occ, sizeof(occ)); - for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++) - for (uint j = 0; j < field->interval->type_lengths[i]; j++) + for (i=0; (val= (unsigned char*) field->typelib()->type_names[i]); i++) + for (uint j = 0; j < field->typelib()->type_lengths[i]; j++) occ[(unsigned int) (val[j])]= 1; if (!occ[(unsigned char)NAMES_SEP_CHAR]) @@ -1127,10 +1127,11 @@ static bool pack_fields(uchar **buff_arg, List &create_fields, int_count= field->interval_id; *buff++= sep; - for (int i=0; field->interval->type_names[i]; i++) + for (int i=0; field->typelib()->type_names[i]; i++) { - memcpy(buff, field->interval->type_names[i], field->interval->type_lengths[i]); - buff+= field->interval->type_lengths[i]; + memcpy(buff, field->typelib()->type_names[i], + field->typelib()->type_lengths[i]); + buff+= field->typelib()->type_lengths[i]; *buff++= sep; } *buff++= 0; @@ -1214,8 +1215,8 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, Record_addr addr(buff + field->offset + data_offset, null_pos + null_count / 8, null_count & 7); Column_definition_attributes tmp(*field); - tmp.interval= field->save_interval ? - field->save_interval : field->interval; + tmp.set_typelib(field->save_interval ? + field->save_interval : field->typelib()); /* regfield don't have to be deleted as it's allocated on THD::mem_root */ Field *regfield= tmp.make_field(&share, thd->mem_root, &addr, field->type_handler(),